python 子进程多个 stdin.write 和 stdout.read
python subprocess multiple stdin.write and stdout.read
感谢您抽出时间回答问题。我正在玩 Python 3.4,我有两个简单的 python 程序。第一,一个名为 test.py 的程序,它接受用户输入并打印一些东西。
while True:
print("enter something...")
x = input()
print(x)
time.sleep(1)
要向该程序发送输入,我有另一个使用子进程的程序:
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())
但是当我运行上面的程序时,我得到一个错误:
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,事情就会按预期进行。
有什么方法可以发送多个 stdin 写入并读回多个 stdout?
一般来说,你应该use pexpect
for interactive programs (dialog-based interactions)。
您的具体问题可能是由 python 版本不匹配引起的(您认为您的代码是使用 Python 3 执行的,而实际上它可能是使用 Python 2 执行的)。第二个问题 (EOFError
) 是预期的:要么在 child 脚本中捕获它,要么为 child 提供退出信号(我在下面的代码示例中使用空行).
这是一个 Python 3 代码,在 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
是当前的 python 可执行文件(在本例中为 Python 3)
universal_newlines=True
启用文本模式(否则,cat.stdin
和 cat.stdout
使用字节,而不是字符串)
-u
使 child 的输出 line-buffered (otherwise, you won't see anything until the child flushes its internal stdout buffer)
with
语句关闭管道并等待 child 进程退出。
这是对应的 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..."
后没有换行
它有效但很脆弱,阅读 Q: Why not just use a pipe (popen())? and use pexpect
instead。
如果输入是有限的并且不依赖于输出,那么您可以一次性全部传递:
#!/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='')
此版本要求 child 正确处理 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)
输出相同(如上图)
感谢您抽出时间回答问题。我正在玩 Python 3.4,我有两个简单的 python 程序。第一,一个名为 test.py 的程序,它接受用户输入并打印一些东西。
while True:
print("enter something...")
x = input()
print(x)
time.sleep(1)
要向该程序发送输入,我有另一个使用子进程的程序:
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())
但是当我运行上面的程序时,我得到一个错误:
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,事情就会按预期进行。
有什么方法可以发送多个 stdin 写入并读回多个 stdout?
一般来说,你应该use pexpect
for interactive programs (dialog-based interactions)。
您的具体问题可能是由 python 版本不匹配引起的(您认为您的代码是使用 Python 3 执行的,而实际上它可能是使用 Python 2 执行的)。第二个问题 (EOFError
) 是预期的:要么在 child 脚本中捕获它,要么为 child 提供退出信号(我在下面的代码示例中使用空行).
这是一个 Python 3 代码,在 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
是当前的 python 可执行文件(在本例中为 Python 3)universal_newlines=True
启用文本模式(否则,cat.stdin
和cat.stdout
使用字节,而不是字符串)-u
使 child 的输出 line-buffered (otherwise, you won't see anything until the child flushes its internal stdout buffer)with
语句关闭管道并等待 child 进程退出。
这是对应的 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..."
它有效但很脆弱,阅读 Q: Why not just use a pipe (popen())? and use pexpect
instead。
如果输入是有限的并且不依赖于输出,那么您可以一次性全部传递:
#!/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='')
此版本要求 child 正确处理 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)
输出相同(如上图)