python – 如何使用`stdin = PIPE`重现`stdin = sys.stdin`?

我有以下代码完全按预期工作:

from subprocess import Popen

process = Popen(
    ["/bin/bash"],stdin=sys.stdin,stdout=sys.stdout,stderr=sys.stderr,)
process.wait()

我可以交互式地使用bash,tab works等.

但是,我想控制我发送到stdin的内容,所以我希望以下工作:

import os
import sys
from subprocess import Popen,PIPE
from select import select

process = Popen(
    ["/bin/bash"],stdin=PIPE,)

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,close_fds=True,)

    while True:
        if process.poll() is not None:
            break

        r,[])

        if sys.stdin in r:
            os.write(master,os.read(stdin,1024))
finally:
    os.close(master)
    os.close(slave)

并且行为非常接近,除了tab仍然不起作用.好吧,tab已正确发送,但我的终端没有显示完成,即使它是由bash完成的.箭头也显示^ [[而不是通过历史记录.

任何的想法?

解决方法

我只需要将我的sys.stdout设置为raw.我还发现了3件事:

>我需要恢复sys.stdout上的终端设置
> subprocess.Popen有一个start_new_session参数,它执行我的_preexec函数正在执行的操作.
> select.select接受第4个参数,这是放弃之前的超时.它让我避免在退出后卡在选择循环中.

最终代码

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"],start_new_session=True,_ = select.select([sys.stdin],0.2)

        if sys.stdin in r:
            os.write(master,1024))
finally:
    termios.tcsetattr(sys.stdout,termios.TCSADRAIN,old_settings)
    os.close(master)
    os.close(slave)

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...