![](/img/trans.png)
[英]subprocess popen.communicate() vs. stdin.write() and 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?
通常,應將pexpect
用於交互式程序(基於對話框的交互) 。
您的特定問題可能是由python版本不匹配引起的(您認為您的代碼是使用Python 3執行的,而實際上可能是使用Python 2執行的)。 第二個問題( EOFError
)是預期的:要么在子腳本中捕獲它,要么提供一個讓孩子退出的信號(在下面的代碼示例中,我使用空行)。
這是一個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
使孩子的輸出行緩沖( 否則,直到孩子刷新其內部stdout緩沖區,您將看不到任何內容 ) with
-statement關閉管道並等待子進程退出。 這是相應的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
。
如果輸入是有限的並且不依賴於輸出,則可以一次全部傳遞:
#!/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:
#!/usr/bin/env python3
import time
while True:
try:
x = input("enter something...")
except EOFError:
break # no more input
print(x)
time.sleep(1)
輸出是相同的(如上所示)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.