Popen([...], stderr=PIPE) 忽略来自生成的 python 程序的 input() 消息
Popen([...], stderr=PIPE) ignores input() message from spawned python program
我有一个文件 运行通过 Popen() 连接另一个文件。
# a.py
import subprocess
p = subprocess.Popen(['python3','/home/scotty/b.py'],
stderr=subprocess.PIPE)
p.wait()
# b.py
input('???')
当我运行a.py“???”没有出现,但提示仍然有效...为什么?我该如何解决?
如果我删除 stderr=subprocess.PIPE 那么“???”确实出现了。
根据文档,输入 "is written to standard output" 的输出,我没有触及标准输出。
似乎在你的例子中,一切都发生了,就好像为 stderr 打开管道而不是为 stdout 打开管道具有将 stdout 重定向到 stderr 的效果,因为在我所做的测试中,stderr 收到输入的提示。
下面是一个适用于我 linux 的代码。它可能过于复杂,因为我使用了 socketpairs,这当然不是必需的,但至少它是健壮的并且可以工作。
##################################
# a.py
import subprocess
import socket
import select
esock, echildsock = socket.socketpair()
osock, ochildsock = socket.socketpair()
p = subprocess.Popen(['python3','b.py'],
stderr=echildsock.fileno(),
stdout=ochildsock.fileno())
while p.poll() is None:
r, w, x = select.select([esock, osock],[],[], 1.0)
if not r:
continue # timed out
for s in r:
print('stdout ready' if s is osock else 'stderr ready')
data = s.recv(1024)
print('received', data.decode('utf8'))
osock.shutdown(socket.SHUT_RDWR)
osock.close()
esock.shutdown(socket.SHUT_RDWR)
esock.close()
##################################
# b.py
res = input('???')
print('in b:', res)
我有一个文件 运行通过 Popen() 连接另一个文件。
# a.py
import subprocess
p = subprocess.Popen(['python3','/home/scotty/b.py'],
stderr=subprocess.PIPE)
p.wait()
# b.py
input('???')
当我运行a.py“???”没有出现,但提示仍然有效...为什么?我该如何解决?
如果我删除 stderr=subprocess.PIPE 那么“???”确实出现了。
根据文档,输入 "is written to standard output" 的输出,我没有触及标准输出。
似乎在你的例子中,一切都发生了,就好像为 stderr 打开管道而不是为 stdout 打开管道具有将 stdout 重定向到 stderr 的效果,因为在我所做的测试中,stderr 收到输入的提示。
下面是一个适用于我 linux 的代码。它可能过于复杂,因为我使用了 socketpairs,这当然不是必需的,但至少它是健壮的并且可以工作。
##################################
# a.py
import subprocess
import socket
import select
esock, echildsock = socket.socketpair()
osock, ochildsock = socket.socketpair()
p = subprocess.Popen(['python3','b.py'],
stderr=echildsock.fileno(),
stdout=ochildsock.fileno())
while p.poll() is None:
r, w, x = select.select([esock, osock],[],[], 1.0)
if not r:
continue # timed out
for s in r:
print('stdout ready' if s is osock else 'stderr ready')
data = s.recv(1024)
print('received', data.decode('utf8'))
osock.shutdown(socket.SHUT_RDWR)
osock.close()
esock.shutdown(socket.SHUT_RDWR)
esock.close()
##################################
# b.py
res = input('???')
print('in b:', res)