持久python子进程

2024-06-02 05:08:10 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中有没有一种方法可以使子进程调用“持久化”?我正在调用一个需要一段时间才能多次加载的程序。所以,如果我能让这个程序保持开放状态,在不破坏它的情况下与它交流,那将是非常好的。

我的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)

如果我能让这个过程保持开放,我会非常感激的。


Tags: textin程序noneforstderrstdinstdout
3条回答

communicate()的调用正在终止子进程。根据subprocess documentationcommunicate()方法将:

Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate.

您要做的是直接与POpen对象的stdinstdout属性交互,以便与子进程通信。然而,文件建议不要这样说:

Warning: Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

因此,您要么需要为潜在的死锁实现自己的解决方案,要么希望有人已经为您编写了asynchronous subprocess module

编辑:下面是一个关于如何使用异步子流程模块的简单示例:

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 

您可以使用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()的函数,并使其在任何可用的情况下返回数据,或者在没有任何数据的情况下引发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()是一个需要编写的函数,它返回True,如果到目前为止收到的数据是您希望得到的所有输出。

我想你在找

myprocess.stdin.write(text)

您可以创建一个popen列表,然后在另一个循环中的每个元素上调用communicate。 像这样的东西

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

这样就不用等到所有的教皇都开始了

相关问题 更多 >