python子进程多个stdin.write和stdout.read [英] python subprocess multiple stdin.write and stdout.read

查看:859
本文介绍了python子进程多个stdin.write和stdout.read的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢您抽出时间回答问题.我正在使用Python 3.4,并且有两个简单的python程序.一个是一个名为test.py的程序,它需要用户输入并打印出一些东西.

Thanks for taking time to answer the question. I am playing around with Python 3.4 and I have two simple python programs. One, a program called test.py that takes a user input and prints something.

while True:
    print("enter something...")
    x = input()
    print(x)
    time.sleep(1)

要向该程序发送输入,我还有另一个使用子进程的程序:

To send input to this program, I have another program that uses subprocess:

from subprocess import Popen, PIPE

cat = Popen('python test.py', shell=True, stdin=PIPE, stdout=PIPE)
cat.stdin.write("hello, world!\n")
cat.stdin.flush()
print(cat.stdout.readline())

cat.stdin.write("and another line\n")
cat.stdin.flush()
print(cat.stdout.readline())

但是,当我运行上述程序时,出现错误:

However when I run the above program, I get an error:

enter something...

hello, world!
Traceback (most recent call last):
  File "/opt/test.py", line 9, in <module>
    x = input()
EOFError: EOF when reading a line
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe

如果我用"cat"之类的标准linux命令替换test.py,一切都会按预期进行.

And if I replace test.py with a standard linux command like 'cat', things work as expected.

我可以通过多种方式发送多个stdin写入并读取多个stdout吗?

Is there any way I send multiple stdin writes and read multiple stdout back?

推荐答案

通常,您应该对交互程序使用pexpect(基于对话框的交互).

In general, you should use pexpect for interactive programs (dialog-based interactions).

您的特定问题可能是由python版本不匹配引起的(您认为您的代码是使用Python 3执行的,而实际上可能是使用Python 2执行的).预期第二个问题(EOFError):要么在子脚本中捕获它,要么提供一个让孩子退出的信号(我在下面的代码示例中使用空行).

Your specific issue might be caused by a python version mismatch (you think your code is executed using Python 3 while actually it might be executed using Python 2). The second issue (EOFError) is expected: either catch it in the child script or provide a signal for the child to exit (I use an empty line for that in the code example below).

这是一个Python 3代码,在Python 2上大声失败

Here's a Python 3 code that fails loudly on Python 2:

#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE

with Popen([sys.executable, '-u', 'test.py'], stdin=PIPE, stdout=PIPE,
           universal_newlines=True, bufsize=1) as cat:
    for input_string in ["hello, world!", "and another line", ""]:
        print(input_string, file=cat.stdin, flush=True)
        print(cat.stdout.readline(), end='')

注意:

  • sys.exectable is the current python executable (Python 3 in this case)
  • universal_newlines=True enables the text mode (otherwise, cat.stdin and cat.stdout work with bytes, not strings)
  • -u makes the child's output line-buffered (otherwise, you won't see anything until the child flushes its internal stdout buffer)
  • the with-statement closes the pipes and waits for the child process to exit.

这是对应的test.py:

#!/usr/bin/env python3
import time

while True:
    x = input("enter something...")
    if not x: # exit if the input is empty
        break
    print(x)
    time.sleep(1)

输出

enter something...hello, world!
enter something...and another line
enter something...

注意:"enter something..."

它可以工作,但很脆弱,请阅读问:为什么不只使用管道(popen())?改用pexpect .

It works but it is fragile, read Q: Why not just use a pipe (popen())? and use pexpect instead.

如果输入是有限的,并且不依赖于输出,则可以一次全部传递它:

If the input is finite and it doesn't depend on the output then you could pass it all at once:

#!/usr/bin/env python3
import sys
from subprocess import check_output

output = check_output([sys.executable, 'test.py'],
                      input="\n".join(["hello, world!", "and another line"]),
                      universal_newlines=True)
print(output, end='')

此版本要求孩子正确处理EOF:

This version requires that the child handles EOF properly:

#!/usr/bin/env python3
import time

while True:
    try:
        x = input("enter something...")
    except EOFError:
        break # no more input

    print(x)
    time.sleep(1)

输出相同(如上所示).

The output is the same (as shown above).

这篇关于python子进程多个stdin.write和stdout.read的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆