有没有办法在python“persistent”中进行子进程调用?我正在调用一个需要一段时间来加载多次的程序。因此,如果我可以将该程序保持打开状态并与之通信而不会将其删除,那就太棒了。
我的python脚本的卡通版本如下所示:
for text in textcollection:
myprocess = subprocess.Popen(["myexecutable"],
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = None)
myoutputtext, err = myprocess.communicate(input=text)
我需要单独处理每个文本,因此将它们全部加入一个大文本文件并处理一次不是一个选项。
最好是,如果有这样的选项
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)
我可以让这个过程开放,我真的很感激。
答案 0 :(得分:25)
您可以使用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
Unix的这种方法的替代方法是将文件句柄置于非阻塞模式,这将允许您调用myprocess.stdout.read()
之类的函数并让它返回数据(如果有),或者引发{{ 1}}如果没有任何数据:
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
在此示例中,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
是您需要编写的函数,如果您到目前为止收到的数据是您希望得到的所有输出,则返回validate_output()
。
答案 1 :(得分:5)
对communicate()
的调用正在杀死你的子进程。根据{{3}},communicate()
方法将:
与流程交互:将数据发送到stdin。从stdout和stderr读取数据,直到达到文件结尾。等待进程终止。
您要做的是直接与POpen
对象的stdin
和stdout
属性进行交互,以便与子进程通信。但是,文档建议不要这样说:
警告:使用communic()而不是.stdin.write,.stdout.read或.stderr.read来避免由于任何其他OS管道缓冲区填满并阻止子进程而导致的死锁。
因此,您需要为潜在的死锁实施自己的变通方法,或者希望有人为您编写subprocess documentation。
编辑:这是一个关于如何使用异步子进程模块的快速示例:
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
当我运行它时,会打印:
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
答案 2 :(得分:1)
我认为你正在寻找
myprocess.stdin.write(text)
你可以创建一个Popens列表,然后在另一个循环中的每个元素上调用communication。 像这样的东西
processes=[]
for text in textcollection:
myprocess = subprocess.Popen(["myexecutable"],
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = None)
myprocess.stdin.write(text)
processes.append(myprocess)
for proc in processes:
myoutput, err=proc.communicate()
#do something with the output here
这样就不必等到所有Popens开始之后
答案 3 :(得分:-2)
if os.name == 'nt':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
subprocess.call(os.popen(tempFileName), shell=True)
os.remove(tempFileName)