我有以下代码,其工作原理与预期完全一致:
from subprocess import Popen
process = Popen(
["/bin/bash"],
stdin=sys.stdin,
stdout=sys.stdout,
stderr=sys.stderr,
)
process.wait()我可以交互使用bash,标签工作,等等。
但是,我想控制我发送给stdin的内容,所以我希望下面的内容能够发挥作用:
import os
import sys
from subprocess import Popen, PIPE
from select import select
process = Popen(
["/bin/bash"],
stdin=PIPE,
stdout=sys.stdout,
stderr=sys.stderr,
)
while True:
if process.poll() is not None:
break
r, _, _ = select([sys.stdin], [], [])
if sys.stdin in r:
stdin = os.read(sys.stdin.fileno(), 1024)
# Do w/e I want with stdin
os.write(process.stdin.fileno(), stdin)
process.wait()但行为就是不一样。我尝试过另一种方法(通过pty):
import os
import sys
import tty
from subprocess import Popen
from select import select
master, slave = os.openpty()
stdin = sys.stdin.fileno()
try:
tty.setraw(master)
ttyname = os.ttyname(slave)
def _preexec():
os.setsid()
open(ttyname, "r+")
process = Popen(
args=["/bin/bash"],
preexec_fn=_preexec,
stdin=slave,
stdout=sys.stdout,
stderr=sys.stderr,
close_fds=True,
)
while True:
if process.poll() is not None:
break
r, _, _ = select([sys.stdin], [], [])
if sys.stdin in r:
os.write(master, os.read(stdin, 1024))
finally:
os.close(master)
os.close(slave)而且行为非常接近,但选项卡仍然不起作用。好吧,选项卡是正确发送的,但是我的终端没有显示完成,尽管它是由bash完成的。箭头还显示^[[A,而不是遍历历史。
有什么想法吗?
发布于 2016-05-29 08:07:36
我所需要的只是将我的sys.stdout设置为raw。我还发现了三件事:
sys.stdout上的终端设置subprocess.Popen有一个start_new_session参数,它执行我的_preexec函数所做的工作。select.select接受第四个参数,这是放弃之前的超时。它使我避免在退出后被困在select循环中。最终代码:
import os
import sys
import tty
import termios
import select
import subprocess
master, slave = os.openpty()
stdin = sys.stdin.fileno()
try:
old_settings = termios.tcgetattr(sys.stdout)
tty.setraw(sys.stdout)
process = subprocess.Popen(
args=["/bin/bash"],
stdin=slave,
stdout=sys.stdout,
stderr=sys.stderr,
close_fds=True,
start_new_session=True,
)
while True:
if process.poll() is not None:
break
r, _, _ = select.select([sys.stdin], [], [], 0.2)
if sys.stdin in r:
os.write(master, os.read(stdin, 1024))
finally:
termios.tcsetattr(sys.stdout, termios.TCSADRAIN, old_settings)
os.close(master)
os.close(slave)https://stackoverflow.com/questions/37371389
复制相似问题