Popen混合数据流?

时间:2013-05-06 10:34:34

标签: python pipe popen

我在Windows上遇到了Popen和Pipes的问题。我认为Popen在stdout和stderr之间混合了数据。 当我的程序只读取stdout时一切正常但是当我读取stdout和stderr时,stdout中的一些数据被抛出到stderr。 我的阅读方法:

    for line in iter(self._read_obj.readline, b''):
        self._queue.put(line)
        sleep(.2)

其中self._read_obj是stderr或stdout。 你知道我怎么解决这个问题?

2 个答案:

答案 0 :(得分:0)

from subproccess import *
x = Popen('sh /root/script.sh', stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=True)
print x.stdout.readline()
print x.stderr.readline()

由于您没有发布任何相关代码,因此它应该如何显示。 请注意,即使没有提取,readline仍然会给你输出,因为stderr有时会“挂起”等待输出,但如果你正在使用子进程,那么这就是你要做的。

from subprocess import PIPE, Popen
x = Popen(['ls', '-l'], stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=False)
while 1:
    if x.poll() != None:
        break
    _queue.put(x.stdout.readline())
    sleep(0.2)

这样的事情应该有用。 如果您不需要将两个输出分开,并且只想读取数据并将其放入队列,则可以执行以下操作:

x = Popen(['ls', '-l'], stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=False)

这是我通常做的事情

(我不是说这是最好的做法,但它确实有效)

from threading import Thread, enumerate
from subprocess import Popen, PIPE
from time import sleep

class nonBlockingStderr(Thread):
    def __init__(self, handle):
        self.handle = handle
        self.stderrOutput = []
        Thread.__init__(self)
        self.start()
    def stderr(self):
        if len(self.stderrOutput) <= 0:
            return ''
        else:
            ret = self.stderrOutput[0]
            self.stderrOutput = self.stderrOutput[1:]
            return ret
    def run(self):
        while 1:
            line = self.handle.readline()
            if len(line) > 0:
                self.stderrOutput.append(line)
            sleep(0.1)

from subprocess import PIPE, Popen
x = Popen(['ls', '-l'], stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=False)
errHandle = nonBlockingStderr(x.stderr)
while 1:
    if x.poll() != None:
        break
    _queue.put(errHandle.stderr())
    _queue.put(x.stdout.readline())
    sleep(0.2)

答案 1 :(得分:0)

分隔stdout / stderr输出的一种简单方法是使用.communicate()

from subprocess import Popen, PIPE

p = Popen(command, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()

它读取内存中的所有输出。

如果要在子进程运行时处理输出;你需要Windows上的线程:

from Queue import Empty, Queue
from subprocess import Popen, PIPE
from threading import Thread

def reader_thread(pipe, process_line):
    for line in iter(pipe.readline, b''):
        process_line(line)
    pipe.close()

def start_reader_thread(pipe, process_line):
    t = Thread(target=reader_thread, args=[pipe, process_line])
    t.daemon = True
    t.start()

q = Queue()
p = Popen(command, stdout=PIPE, stderr=PIPE, bufsize=1)
start_reader_thread(p.stdout, lambda line: q.put(('stdout', line)))
start_reader_thread(p.stderr, lambda line: q.put(('stderr', line)))

while p.poll() is None: # while subprocess is running
    try:
        source, line = q.get_nowait()
    except Empty:
        pass
    else:
        # use source, line here
        print(source, line)
q.put(None)
for source, line in iter(q.get, None): # process the rest
    # use source, line here
    print("after", source, line)