使用 subprocess.Popen 调用 python 脚本并刷新数据
问题描述
好吧,我已经看到了十几个这样的主题,但没有一个给出完整的答案,而且到目前为止我尝试的一切都对我不起作用.
Ok so i've seen dozen of threads like that , but none of them gives a complete answer and everything i tried so far foes not work for me.
1) 不断输出一些数据并刷新它的脚本:
import time
import sys
if __name__ == '__main__':
for i in range(5):
print i,
sys.stdout.flush()
time.sleep(1)
2) 使用 Popen 调用第一个脚本的脚本,应该一个一个地打印数字,但由于某种原因没有,并且一次打印它们:
import sys
import subprocess
if __name__ == '__main__':
process = subprocess.Popen(['python', 'flush.py'], stdout = subprocess.PIPE )
for line in iter(process.stdout.readline, ''):
print line,
sys.stdout.flush()
我有点困惑的第一件事是在 first 脚本中,如果你删除刷新,它会在一行中返回输出 O_O...我很确定这是因为时间.sleep 但仍然有点期望它像标准输出一样返回,不断返回值 0,1,2,3,4 但不是全部一起,当然 flush 解决了它,但只是奇怪,至少对我来说......
First thing i am a little bit confused is in the first script is that if you remove the flush it returns output in one line alltogether O_O... I am pretty sure it is because of time.sleep but still kind of expected it return like a standart output constantly returning values 0,1,2,3,4 but not all together, ofcourse flush resolves it , but just strange, at least for me ...
主要问题:是不是第二个脚本不会一一返回数字,而是一次返回所有输出......我需要的是看到数字一一弹出......
The main problem: Is that second script does not return number one by one , but returns all in one output at once..... What i need is to see numbers popping one by one...
我在某处读到它不返回 Popen 等待关闭管道的 EOF,这就是它运行到最后的原因.....
I read somewhere that it does not return EOF which Popen waits to close the pipe , thats why it runs like to the end .....
那么接下来我该怎么做或尝试呢?提前致谢.
So what do i do or try next ? Thanks in advance.
解决方案
As @Warren Weckesser 的评论 说,您的问题与缓冲问题无关.
As @Warren Weckesser's comment says, your problem is unrelated to buffering issues.
.readline()
在读取换行符或到达 EOF 之前不会返回.您的子进程根本不会打印 any 换行符,因此您的父进程在子进程结束之前不会打印 anything.
.readline()
in the parent process won't return until it reads a newline or reaches EOF. Your child process doesn't print any newlines at all so your parent process doesn't print anything until the child process ends.
最小的解决方法是删除子脚本中 print i,
末尾的逗号.
The minimal fix is just to remove comma at the end of print i,
in the child script.
这也有效:
#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE
p = Popen([sys.executable or 'python',
'-u', # unbuffer stdout (or make it line-buffered on Python 3)
'-c',
"""
import time
for i in range(5):
print(i) # <-- no comma i.e., each number is on its own line
time.sleep(1)
"""], stdout=PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
print(int(line)**2)
例子:
$ python parent.py
0
1
4
9
16
数字每秒钟打印一次,无需等待子进程结束.
The numbers are printed every seconds without waiting for the child process to end.
如果您不想更改子脚本,那么您应该使用 readline()
停止在空白处而不是换行符,例如:
If you don't want to change the child script then you should use readline()
that stops at whitespace instead of a newline character e.g.:
#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE
p = Popen(['python2', 'child.py'], stdout=PIPE, bufsize=0)
for token in generate_tokens(p.stdout):
print(int(token))
其中 generate_tokens()
产生空格分隔的标记:
where generate_tokens()
yields whitespace-separated tokens:
def generate_tokens(pipe):
buf = []
while True:
b = pipe.read(1) # read one byte
if not b: # EOF
pipe.close()
if buf:
yield b''.join(buf)
return
elif not b.isspace(): # grow token
buf.append(b)
elif buf: # full token read
yield b''.join(buf)
buf = []
它也会在孩子打印出整数后立即打印出来.
It also prints integers as soon as they are printed by the child.
相关文章