你只能与子进程通信一次吗?

时间:2009-11-04 20:17:52

标签: python subprocess

communicate的文档说:

  

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

如果您需要多次向流程发送输入,该怎么办?例如,我生成一个进程,发送一些数据,进程执行某些操作,返回一些输出,然后我必须再次发送输入?我该如何处理?

4 个答案:

答案 0 :(得分:3)

然后你不能使用.communicate()。您可以轮询流,使用select或其他一些允许您收听FD更改的方式(例如,gtk和Qt都有工具)。

答案 1 :(得分:3)

看看Doug Hellman's Python Module of the Week writeup about subprocess。向下搜索,直到看到“repeater.py”。

在那里,您将找到如何向进程发送和接收输入/输出的示例。

答案 2 :(得分:2)

不要使用subprocess,你将进入缓冲的痛苦世界。

我为此目的推荐pexpect - 它运作良好。不幸的是,它目前在Windows下不起作用,虽然我确实听说过一个端口(我找不到了)。

答案 3 :(得分:1)

这是我写的一个模块。确保使用该-u参数以避免缓冲问题:

import os
import pickle
import subprocess
from subprocess import PIPE
import struct
import builtins
def call_thru_stream(stream,funcname,*args,**kwargs):
    """Used for calling a function through a stream and no return value is required. It is assumed
    the receiving program is in the state where it is expecting a function."""
    transmit_object(stream,(funcname,args,kwargs))


def function_thru_stream(in_stream,out_stream,funcname,*args,**kwargs):
    """Used for calling a function through a stream where a return value is required. It is assumed
    the receiving program is in the state where it is expecting a function."""
    transmit_object(in_stream,(funcname,args,kwargs))
    return receive_object(out_stream)

#--------------------- Object layer ------------------------------------------------------------

def transmit_object(stream,obj):
    """Transmits an object through a binary stream"""
    data=pickle.dumps(obj,2)#Uses pickle version 2 for compatibility with 2x
    transmit_atom(stream,data)


def receive_object(stream):
    """Receive an object through a binary stream"""
    atom=receive_atom(stream)
    return pickle.loads(atom)

#--------------------- Atom layer --------------------------------------------------------------
def transmit_atom(stream, atom_bytes):
    """Used for transmitting a some bytes which should be treated as an atom through
    a stream. An integer indicating the size of the atom is appended to the start."""
    header=struct.pack("=L",len(atom_bytes))
    stream.write(header)
    stream.write(atom_bytes)
    stream.flush()


def receive_atom(stream):
    """Read an atom from a binary stream and return the bytes."""
    input_len=stream.read(4)
    l=struct.unpack("=L",input_len)[0]
    return stream.read(l)