Skip to content

Commit e4df149

Browse files
committed
Use custom run executable to pipe subprocess output
1 parent a261b77 commit e4df149

File tree

1 file changed

+58
-3
lines changed

1 file changed

+58
-3
lines changed

clearpath_generator_common/test/generate_samples.py

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
"""Scripts to generate samples using the clearpath_generator_common."""
22
import argparse
33
import os
4+
import signal
45
import shutil
6+
import subprocess
7+
import sys
58

69
from ament_index_python.packages import get_package_share_directory
710
from clearpath_generator_common.bash.generator import BashGenerator
@@ -25,6 +28,50 @@ def __init__(self, message, errors):
2528
self.errors = errors
2629

2730

31+
def run_ros2_executable(*, path, argv, prefix=None):
32+
"""Execute a ROS2 executable."""
33+
cmd = [path] + argv
34+
35+
# on Windows Python scripts are invokable through the interpreter
36+
if os.name == 'nt' and path.endswith('.py'):
37+
cmd.insert(0, sys.executable)
38+
39+
if prefix is not None:
40+
cmd = prefix + cmd
41+
42+
process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
43+
44+
# add signal handler for the parent process, so that we can finalize the child process
45+
def signal_handler(sig, frame):
46+
print('[ros2run]', 'Received signal: ', signal.strsignal(sig))
47+
if process.poll() is None:
48+
# If child process is running, forward the signal to it
49+
process.send_signal(sig)
50+
signal.signal(signal.SIGINT, signal_handler)
51+
signal.signal(signal.SIGTERM, signal_handler)
52+
53+
stdout = ''
54+
stderr = ''
55+
56+
while process.returncode is None:
57+
try:
58+
out, err = process.communicate()
59+
stdout += out.decode('utf-8')
60+
stderr += err.decode('utf-8')
61+
except KeyboardInterrupt:
62+
# the subprocess will also receive the signal and should shut down
63+
# therefore we continue here until the process has finished
64+
pass
65+
if process.returncode != 0:
66+
if -process.returncode in signal.valid_signals() and os.name == 'posix':
67+
# a negative value -N indicates that the child was terminated by signal N.
68+
print('[ros2run]', signal.strsignal(-process.returncode))
69+
else:
70+
# print general failure message instead.
71+
print('[ros2run]', 'Process exited with failure %d' % (process.returncode))
72+
return (process.returncode, stdout, stderr)
73+
74+
2875
def generate_bash(setup_path) -> None:
2976
"""Generate bash environment file."""
3077
bg = BashGenerator(setup_path)
@@ -75,10 +122,16 @@ def generate_semantic_description(setup_path: str) -> bool:
75122
'--min-collision-fraction', '0.95',
76123
'--ros-args', '--log-level', 'fatal'
77124
]
78-
run_executable(path=path, argv=argv)
125+
ret, out, err = run_ros2_executable(path=path, argv=argv)
79126
# Delete pseudo package
80127
os.remove(os.path.join(setup_path, 'package.xml'))
81128

129+
if ret == 0:
130+
print(f'Generated {os.path.join(setup_path)}/robot.srdf')
131+
else:
132+
print(f'Failed to generate {os.path.join(setup_path)}/robot.srdf')
133+
raise Exception(f'Failed semantic generation with \n\tstdout:{out} \n\tstderr: {err}')
134+
82135

83136
def error_log(name: str, sample: str, error: Exception) -> str:
84137
"""Return error entry."""
@@ -95,7 +148,7 @@ def generate_test_samples(root_dir: str):
95148
# Filter for Test Samples
96149
if 'test' not in sample:
97150
continue
98-
print(sample)
151+
print(f'Generating {sample}'.center(100, '-'))
99152
# Create Clearpath Directory
100153
src = os.path.join(sample_dir, sample)
101154
dst = os.path.join(
@@ -138,8 +191,10 @@ def generate_test_samples(root_dir: str):
138191
except Exception as e:
139192
errors.append(error_log('SemanticDescriptionGenerator', sample, e))
140193
if len(errors) > 0:
141-
sample_errors.append(f'Sample "{sample}" failed to generate:\n''\n '.join(errors))
194+
sample_errors.append(f'Sample "{sample}" failed to generate:\n{'\n '.join(errors)}')
195+
print()
142196
if len(sample_errors) > 0:
197+
print(f'Generators reported {len(sample_errors)} errors'.center(100, '*'))
143198
raise GenerationFailureException(
144199
message=f'Generation failed for {len(sample_errors)} samples:\n'
145200
f'{"\n".join(sample_errors)}',

0 commit comments

Comments
 (0)