Jas*_*ond 10 python subprocess
有没有办法在python"持久"中进行子进程调用?我正在调用一个需要一段时间来加载多次的程序.因此,如果我可以让该程序保持打开并与之通信而不会将其删除,那将会很棒.
我的python脚本的卡通版本如下所示:
for text in textcollection:
myprocess = subprocess.Popen(["myexecutable"],
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = None)
myoutputtext, err = myprocess.communicate(input=text)
Run Code Online (Sandbox Code Playgroud)
我需要单独处理每个文本,因此将它们全部加入一个大文本文件并处理一次不是一个选项.
最好是,如果有这样的选项
myprocess = subprocess.Popen(["myexecutable"],
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = None) for text in textcollection:
for text in textcollection:
myoutputtext, err = myprocess.communicate(input=text)
Run Code Online (Sandbox Code Playgroud)
我可以把这个过程打开,我真的很感激.
And*_*ark 26
您可以使用myprocess.stdin.write()和myprocess.stdout.read()与子进程通信,您只需要小心确保正确处理缓冲以防止阻止您的呼叫.
如果您的子进程的输出是明确定义的,您应该能够使用行缓冲和可靠地与它进行通信myprocess.stdout.readline().
这是一个例子:
>>> p = subprocess.Popen(['cat'], bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> p.stdin.write('hello world\n')
>>> p.stdout.readline()
'hello world\n'
>>> p.stdout.readline() # THIS CALL WILL BLOCK
Run Code Online (Sandbox Code Playgroud)
Unix的这种方法的替代方法是将文件句柄置于非阻塞模式,这将允许您调用函数myprocess.stdout.read(),并使其返回数据(如果有),或者IOError如果没有任何数据则引发:
>>> p = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> import fcntl, os
>>> fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
0
>>> p.stdout.read() # raises an exception instead of blocking
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 11] Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)
这可以让你做这样的事情:
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
for text in textcollection:
myprocess.stdin.write(text + '\n')
while True:
myoutputtext = ''
try:
myoutputtext += myprocess.stdout.read()
except IOError:
pass
if validate_output(myoutputtext):
break
time.sleep(.1) # short sleep before attempting another read
Run Code Online (Sandbox Code Playgroud)
在这个例子中,如果您到目前为止收到的数据是您希望得到的所有输出,那么validate_output()您需要编写的函数将返回True.
调用communicate()就是杀死你的子进程.根据子流程文档,该communicate()方法将:
与流程交互:将数据发送到stdin.从stdout和stderr读取数据,直到达到文件结尾.等待进程终止.
您想要做的是直接与POpen对象stdin和stdout属性交互以与子进程通信.但是,文档建议不要这样说:
警告:使用communic()而不是.stdin.write,.stdout.read或.stderr.read来避免由于任何其他OS管道缓冲区填满和阻止子进程而导致的死锁.
因此,您需要为潜在的死锁实现自己的变通方法,或者希望有人为您编写了异步子流程模块.
编辑:这是一个如何使用异步子进程模块的快速例子:
import asyncsubprocess
textcollection = ['to', 'be', 'or', 'not', 'to be', 'that is the', 'question']
myprocess = asyncsubprocess.Popen(["cat"],
stdin = asyncsubprocess.PIPE,
stdout = asyncsubprocess.PIPE,
stderr = None)
for text in textcollection:
bytes_sent, myoutput, err = myprocess.listen(text)
print text, bytes_sent, myoutput, err
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它打印:
to 2 to
be 2 be
or 2 or
not 3 not
to be 5 to be
that is the 11 that is the
question 8 question
Run Code Online (Sandbox Code Playgroud)