持久化python子进程

持久化python子进程,python,subprocess,Python,Subprocess,有没有一种方法可以在python中进行“持久化”子进程调用?我正在调用一个需要一段时间才能加载多次的程序。所以,如果我能让这个程序保持打开状态,并且在不杀死它的情况下与它通信,那将是一件非常棒的事情 我的python脚本的卡通版本如下所示: for text in textcollection: myprocess = subprocess.Popen(["myexecutable"], stdin = subprocess.PIPE, stdout =

有没有一种方法可以在python中进行“持久化”子进程调用?我正在调用一个需要一段时间才能加载多次的程序。所以,如果我能让这个程序保持打开状态,并且在不杀死它的情况下与它通信,那将是一件非常棒的事情

我的python脚本的卡通版本如下所示:

for text in textcollection:
    myprocess = subprocess.Popen(["myexecutable"],
                stdin = subprocess.PIPE, stdout = subprocess.PIPE,
                stderr = None)
    myoutputtext, err = myprocess.communicate(input=text)
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
我需要单独处理每个文本,所以将所有文本合并到一个大文本文件中并处理一次是不可取的

最好是,如果有这样的选择

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

如果我能让流程保持开放状态,我将非常感激。

我想您正在寻找

myprocess.stdin.write(text)
您可以创建一个popen列表,然后在另一个循环中的每个元素上调用communicate。 像这样的

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

这样,它就不必等到所有的popen都启动后才开始执行

调用
communicate()
,从而终止了您的子进程。根据
communicate()
方法将:

与进程交互:向stdin发送数据。从stdout和stderr读取数据,直到到达文件末尾。等待进程终止

您要做的是直接与
POpen
对象的
stdin
stdout
属性交互,以便与子流程通信。但是,文件建议不要使用这种说法:

警告:请使用communicate()而不是.stdin.write、.stdout.read或.stderr.read,以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致死锁

因此,您要么需要为潜在的死锁实施您自己的解决方案,要么希望有人为您编写了一个解决方案

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

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

在本例中,
validate_output()
是一个需要编写的函数,如果到目前为止您收到的数据都是您希望得到的输出,那么它将返回
True

不幸的是,这对我来说不起作用,因为它是一个java程序,每次运行都会消耗大约3G内存。这就是为什么要花这么长时间来加载。我不能有5000个3G进程的实例,我想我理解。在获得输入文本后,它会输出一些内容,然后退出?还是等着你输入其他东西!我最喜欢你的解决方案,因为它不需要第三方下载。不幸的是,这对我不起作用。在尝试了一些东西之后,我很确定这是我调用的java程序的问题,而不是您的解决方案,所以您的解决方案是好的。这是错误的。在编辑任何内容之前,我的upvote处于非活动状态,但我看不到任何改进或不受影响的内容。回答得很好。@hynekcer,没问题,谢谢您的回复:)只做了一个小的编辑。给我错误`myprocess.stdout.read()文件”/usr/local/cillar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/codecs.py”,第321行,解码数据=self.buffer+输入类型错误:无法将非类型转换为字节`
if os.name == 'nt':
 startupinfo = subprocess.STARTUPINFO()
 startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW
 subprocess.call(os.popen(tempFileName), shell=True)
 os.remove(tempFileName)