wak*_*aka 5 python subprocess pipe python-3.x
感谢您抽出时间回答问题。我正在使用 Python 3.4,并且有两个简单的 python 程序。一是一个名为 test.py 的程序,它接受用户输入并打印一些内容。
while True:
print("enter something...")
x = input()
print(x)
time.sleep(1)
Run Code Online (Sandbox Code Playgroud)
为了将输入发送到该程序,我有另一个使用子进程的程序:
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())
Run Code Online (Sandbox Code Playgroud)
但是,当我运行上面的程序时,出现错误:
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
Run Code Online (Sandbox Code Playgroud)
如果我用标准的 Linux 命令(如“cat”)替换 test.py,一切都会按预期进行。
有什么方法可以发送多个标准输入写入并读回多个标准输出吗?
一般来说,您应该用于pexpect交互式程序(基于对话框的交互)。
您的具体问题可能是由 python 版本不匹配引起的(您认为您的代码是使用 Python 3 执行的,而实际上它可能是使用 Python 2 执行的)。第二个问题 ( EOFError) 是预期的:要么在子脚本中捕获它,要么为子脚本提供退出信号(我在下面的代码示例中使用空行)。
下面是一个在 Python 2 上严重失败的 Python 3 代码:
#!/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='')
Run Code Online (Sandbox Code Playgroud)
笔记:
sys.exectable是当前的 python 可执行文件(在本例中为 Python 3)universal_newlines=True启用文本模式(否则,cat.stdin使用cat.stdout字节,而不是字符串)-u使子进程的输出行缓冲(否则,在子进程刷新其内部 stdout 缓冲区之前您将看不到任何内容)with关闭管道并等待子进程退出。这是相应的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)
Run Code Online (Sandbox Code Playgroud)
enter something...hello, world!
enter something...and another line
enter something...
Run Code Online (Sandbox Code Playgroud)
注意:后面没有新行"enter something..."
它可以工作,但很脆弱,请阅读问:为什么不直接使用管道(popen())?并使用pexpect.
如果输入是有限的并且不依赖于输出,那么您可以一次将其全部传递:
#!/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='')
Run Code Online (Sandbox Code Playgroud)
此版本要求子进程正确处理 EOF:
#!/usr/bin/env python3
import time
while True:
try:
x = input("enter something...")
except EOFError:
break # no more input
print(x)
time.sleep(1)
Run Code Online (Sandbox Code Playgroud)
输出是相同的(如上所示)。
| 归档时间: |
|
| 查看次数: |
8278 次 |
| 最近记录: |