我在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。 你知道我怎么解决这个问题?
答案 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)