您已经发现了问题所在,即子进程输出最后一行后,它仍会继续运行一秒钟,因此当程序处于循环中时,将始终可以看到该程序正在运行。即使您将调用移至循环外的poll,您也可能需要稍等片刻才能让子进程在输出其最终消息后有机会终止(我已经减小了循环大小——生命太短了):
#!/usr/bin/env python3
import subprocess
import shlex
import time
def main():
cmd = 'bash -c "for i in $(seq 1 5);do echo $i; sleep 1; done;"'
print(cmd)
p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, universal_newlines=True)
for line in p.stdout:
print(f"file_name: {line.strip()}", flush=True)
print(p.poll())
time.sleep(.1)
print(p.poll())
if __name__ == "__main__":
main()
打印:
bash -c "for i in $(seq 1 5);do echo $i; sleep 1; done;"
file_name: 1
file_name: 2
file_name: 3
file_name: 4
file_name: 5
None
0
要在循环内“让它工作”,需要对子流程内发生的事情有特殊的了解。根据前面的代码,我们需要:
#!/usr/bin/env python3
import subprocess
import shlex
import time
def main():
cmd = 'bash -c "for i in $(seq 1 5);do echo $i; sleep 1; done;"'
print(cmd)
p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, universal_newlines=True)
for line in p.stdout:
# has to be greater than the sleep time in the subprocess to give the subprocess a chance to terminate
print(f"file_name: {line.strip()}", flush=True)
time.sleep(1.1)
print(p.poll())
if __name__ == "__main__":
main()
打印:
bash -c "for i in $(seq 1 5);do echo $i; sleep 1; done;"
file_name: 1
None
file_name: 2
None
file_name: 3
None
file_name: 4
None
file_name: 5
0
但这几乎不是一个实用的解决方案。人们不得不问进行这项民意调查的原因是什么?它没有提供任何有用的信息,除非您愿意在读取之后包含 sleep 调用因为在子进程完成最后一次写入及其终止之后总会有一些延迟,并且这些 sleep 调用一般都是浪费。您应该一直阅读,直到没有更多输出,然后执行 p.wait() 以等待子进程终止,但这是您的选择:
#!/usr/bin/env python3
import subprocess
import shlex
def main():
cmd = 'bash -c "for i in $(seq 1 5);do echo $i; sleep 1; done;"'
print(cmd)
p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, universal_newlines=True)
for line in p.stdout:
print(f"file_name: {line.strip()}", flush=True)
p.wait()
if __name__ == "__main__":
main()