0

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

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

其中 self._read_obj 是标准错误或标准输出。你知道我该如何解决这个问题吗?

4

2 回答 2

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)
于 2013-05-20T07:46:08.940 回答
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)
于 2013-05-06T10:42:20.057 回答