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

python – 如何使用`stdin = PIPE`重现`stdin = sys.stdin`?,第1张

概述我有以下代码完全按预期工作: from subprocess import Popenprocess = Popen( ["/bin/bash"], stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,)process.wait() 我可以交互式地使用bash,tab works等. 但是,我想控制我发 我有以下代码完全按预期工作:

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

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

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

import osimport sysfrom subprocess import Popen,PIPEfrom select import selectprocess = 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 osimport sysimport ttyfrom subprocess import Popenfrom select import selectmaster,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 osimport sysimport ttyimport termiosimport selectimport subprocessmaster,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)
总结

以上是内存溢出为你收集整理的python – 如何使用`stdin = PIPE`重现`stdin = sys.stdin`?全部内容,希望文章能够帮你解决python – 如何使用`stdin = PIPE`重现`stdin = sys.stdin`?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1197618.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存