Python - 子进程和python shell

时间:2011-12-01 05:36:02

标签: python popen python-idle subprocess

我试图向非python子进程发出shell并允许它从python继承stdin和stdout。 - 我正在使用subprocess.Popen

如果我从控制台调用,这可能会有效,但是当我使用python shell时它肯定不起作用

(我顺便使用IDLE)

有没有办法说服python允许非python子进程将它的stdout打印到python shell?

2 个答案:

答案 0 :(得分:6)

这既适用于脚本,也适用于交互式解释器,但不适用于IDLE:

subprocess.Popen(whatever, stdin=sys.stdout, stdout=sys.stdin)

您不能将IDLE分配给sys.stdinsys.stdout的对象用作subprocess.Popen的参数。这些对象(IDLE shell窗口的接口)是类文件,但它们不是具有fileno属性的真实文件句柄,而类Unix操作系统需要将fileno指定为stdin或stdout一个子流程。我不能代表Windows,但我想它有类似的要求。

答案 1 :(得分:4)

Taymon的答案直接解决了你的问题,因为IDLE的stdin / stdout实际上是类文件对象,而不是与控制台/终端关联的标准文件流。此外,在Windows IDLE中运行pythonw.exe,它甚至没有附加的win32控制台。

也就是说,如果您只需要将程序的输出实时打印给用户,那么在许多情况下(但不是全部)您可以逐行读取输出并相应地回显它。以下适用于Windows IDLE。它演示了从管道stdout逐行读取。它还显示了如果进程缓冲管道会发生什么,在这种情况下readline将阻塞,直到缓冲区已满或管道关闭。可以使用某些程序(例如Python解释器的-u选项)手动禁用此缓冲,并且还有针对Unix的解决方法,例如stdbuf

test1.py

import sys
import subprocess

def test(cmd):
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, 
                         stderr=subprocess.PIPE)
    it = iter(p.stdout.readline, b'')
    for line in it:
        print(line.rstrip().decode('ascii'))

print('Testing buffered subprocess...')
test([sys.executable, 'test2.py'])

print('\nTesting unbuffered subprocess...')
#-u: unbuffered binary stdout and stderr
test([sys.executable, '-u', 'test2.py']) 

test2.py:

import time

for i in range(5):
    print(i)
    time.sleep(1)

IDLE中的输出应如下所示,第一组数字在延迟后一次打印,第二组数字逐行打印。

Testing buffered subprocess...
0
1
2
3
4

Testing unbuffered subprocess...
0
1
2
3
4