我使用子进程模块在python中同时运行两个进程:
p_topic = subprocess.Popen(['rostopic','echo','/msg/address'], stdout=PIPE)
p_play = subprocess.Popen(['rosbag','play',bagfile_path])
这些是ROS进程:p_topic
侦听要播放的.bag
文件,并将该.bag
文件中的某些信息输出到stdout流;我想使用p_topic.stdout
对象(表现为文件)访问此输出。
然而,我发现的事情是p_topic.stdout
对象只包含它应该具有的第一个〜1/3的输出行 - 也就是说,与手动运行这两个命令相比,同时在两个shell中并排。
我已经尝试等待很长时间才能完成输出,但这并没有改变任何东西,它每次都被p_topic.stdout
捕获的线的比例大致相同。任何关于这可能是什么的提示将不胜感激!
编辑:
以下是阅读代码:
#wait for playing to stop
while p_play.poll() == None:
time.sleep(.1)
time.sleep(X)#wait for some time for the p_topic to finish
p_topic.terminate()
output=[]
for line in p_topic.stdout:
output.append(line)
请注意,time.sleep(X)中的值X没有任何区别
答案 0 :(得分:1)
默认情况下,当进程的stdout
未连接到终端时,输出将被块缓冲。连接到终端时,它的线路缓冲。您希望获得完整的行,但除非rostopic
取消缓冲或显式行缓冲区stdout
(如果它是C程序,您可以使用setvbuf
自动执行此操作)。
另一种(可能是重叠的)可能性是管道缓冲区本身正在填充(管道缓冲区通常相当小),并且因为你永远不会消耗它,rostopic
填充管道缓冲区然后无限制地阻塞直到你杀死它,当你阅读过程的stdout
时,只留下管道中适合排水的东西。在这种情况下,您需要生成一个线程以防止管道从Python中耗尽,或者让主线程使用select
模块组件来监视和排空管道(与轮询其他进程混合)。该线程通常更容易,但您需要小心避免线程安全问题。
答案 1 :(得分:0)
是否值得尝试流程沟通/等待?而不是睡觉,这会解决你的问题吗?
我将此作为一般用途,因此不确定您是否可以将其更改为您需要的内容?
executable_Params = "{0} {1} {2} {3} {4}".format(my_Binary,
arg1,
arg2,
arg3,
arg4)
# execute the process
process = subprocess.Popen(shlex.split(executable_Params),
shell=False,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
stdout, stderr = process.communicate()
ret_code = process.wait()
if ret_code == 0:
return 0
else:
#get the correct message from my enum method
error_msg = Process_Error_Codes(ret_code).name
raise subprocess.CalledProcessError(returncode=ret_code,
cmd=executable_Params)