持久的python子进程

2022-01-18 00:00:00 python subprocess

问题描述

有没有办法在python持久"中进行子进程调用?我正在调用一个需要一段时间才能多次加载的程序.因此,如果我可以让该程序保持打开状态并与其通信而不杀死它,那就太好了.

Is there a way to make a subprocess call in python "persistent"? I'm calling a program that takes a while to load multiple times. So it would be great if I could just leave that program open and communicate with it without killing it.

我的python脚本的卡通版是这样的:

The cartoon version of my python script looks like this:

for text in textcollection:
    myprocess = subprocess.Popen(["myexecutable"],
                stdin = subprocess.PIPE, stdout = subprocess.PIPE,
                stderr = None)
    myoutputtext, err = myprocess.communicate(input=text)

我需要单独处理每个文本,因此将它们全部加入一个大文本文件并处理一次不是一种选择.

I need to process each text separately, so joining it all into one large text file and processing it once is not an option.

如果有这样的选择最好

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)

如果我可以让流程保持开放状态,我将不胜感激.

where I can leave the process open, I'd really appreciate it.


解决方案

您可以使用 myprocess.stdin.write()myprocess.stdout.read() 来与您的子进程通信,您只需要小心确保正确处理缓冲以防止调用阻塞.

You can use myprocess.stdin.write() and myprocess.stdout.read() to communicate with your subprocess, you just need to be careful to make sure you handle buffering correctly to prevent your calls from blocking.

如果子进程的输出定义明确,您应该能够使用行缓冲和 myprocess.stdout.readline() 可靠地与其通信.

If the output from your subprocess is well-defined, you should be able to reliably communicate with it using line-buffering and myprocess.stdout.readline().

这是一个例子:

>>> p = subprocess.Popen(['cat'], bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> p.stdin.write('hello world
')
>>> p.stdout.readline()
'hello world
'
>>> p.stdout.readline()        # THIS CALL WILL BLOCK

对于 Unix,此方法的替代方法是将文件句柄置于非阻塞模式,这将允许您调用像 myprocess.stdout.read() 之类的函数并让它返回数据,如果any 可用,如果没有任何数据,则引发 IOError:

An alternative to this method for Unix is to put the file handle in non-blocking mode, which will allow you to call functions like myprocess.stdout.read() and have it return data if any is available, or raise an IOError if there isn't any data:

>>> 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

这将允许您执行以下操作:

This would allow you to do something like this:

fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
for text in textcollection:
    myprocess.stdin.write(text + '
')
    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得到.

In this example, validate_output() is a function you would need to write that returns True if the data you have received so far is all of output that you expect to get.

相关文章