Python的解释器默认启用输出缓冲sys.stdout吗?
如果答案是肯定的,那么禁用它的所有方法是什么?
建议到目前为止:
-u命令行开关sys.stdout在每次写入后刷新的对象PYTHONUNBUFFEREDenv varsys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)是否有任何其他方式来设置一些全局标志sys/ sys.stdout程序执行过程中?
要从我的Python脚本启动程序,我使用以下方法:
def execute(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = process.communicate()[0]
exitCode = process.returncode
if (exitCode == 0):
return output
else:
raise ProcessException(command, exitCode, output)
Run Code Online (Sandbox Code Playgroud)
因此,当我启动一个类似的过程时Process.execute("mvn clean install"),我的程序会一直等到过程结束,然后我才能获得程序的完整输出.如果我正在运行需要一段时间才能完成的过程,这很烦人.
我可以让我的程序逐行写入进程输出,通过在循环结束之前轮询进程输出或其他内容吗?
**[编辑]抱歉,在发布此问题之前我没有很好地搜索.线程实际上是关键.在这里找到一个示例,说明如何执行此操作:** 来自线程的Python Subprocess.Popen
我想将子进程的stderr输出重定向到stdout.常数STDOUT应该这样做,不应该吗?
然而,
$ python >/dev/null -c 'import subprocess;\
subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'
Run Code Online (Sandbox Code Playgroud)
做输出的东西.为什么会这样,我如何在stdout上收到错误消息?
可能重复:
包装子进程'stdout/stderr
在这个问题中,hanan-n询问是否可以将python子进程输出到stdout,同时还将输出保存在字符串中以便以后处理.在这种情况下,解决方案是遍历每个输出行并手动打印它们:
output = []
p = subprocess.Popen(["the", "command"], stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, ''):
print(line)
output.append(line)
Run Code Online (Sandbox Code Playgroud)
但是,此解决方案并未概括为您要为stdout和stderr执行此操作的情况,同时满足以下条件:
我查看了子进程文档,但找不到任何可以实现此目的的东西.我能找到的最接近的是添加stderr=subprocess.stdout和使用与上面相同的解决方案,但是我们失去了常规输出和错误之间的区别.有任何想法吗?我猜测解决方案 - 如果有的话 - 将涉及异步读取p.stdout和p.stderr.
这是我想做的一个例子:
p = subprocess.Popen(["the", "command"])
p.wait() # while p runs, the command's stdout and stderr should behave as usual
p_stdout = p.stdout.read() # unfortunately, this will return '' unless you use subprocess.PIPE
p_stderr = p.stderr.read() # ditto
[do something …Run Code Online (Sandbox Code Playgroud) 是否可以修改以下代码以从'stdout'和'stderr'打印输出:
代码:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import subprocess
def run_cmd(command, cwd=None):
p = subprocess.Popen(command, cwd=cwd, shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
outs, errs = p.communicate()
rc = p.returncode
outs = outs.decode('utf-8')
errs = errs.decode('utf-8')
return (rc, (outs, errs))
Run Code Online (Sandbox Code Playgroud)
感谢@unutbu,特别感谢@ jf-sebastian,最终功能:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from queue import Queue
from subprocess import PIPE, Popen
from threading import Thread
def read_output(pipe, funcs):
for line in iter(pipe.readline, b''):
for func in funcs: …Run Code Online (Sandbox Code Playgroud) 我一直在编写一个小的Python脚本,它使用subprocess模块和辅助函数执行一些shell命令:
import subprocess as sp
def run(command, description):
"""Runs a command in a formatted manner. Returns its return code."""
start=datetime.datetime.now()
sys.stderr.write('%-65s' % description)
s=sp.Popen(command, shell=True, stderr=sp.PIPE, stdout=sp.PIPE)
out,err=s.communicate()
end=datetime.datetime.now()
duration=end-start
status='Done' if s.returncode==0 else 'Failed'
print '%s (%d seconds)' % (status, duration.seconds)
Run Code Online (Sandbox Code Playgroud)
以下行读取标准输出和错误:
s=sp.Popen(command, shell=True, stderr=sp.PIPE, stdout=sp.PIPE)
out,err=s.communicate()
Run Code Online (Sandbox Code Playgroud)
如您所见,未使用stdout和stderr.假设我想以格式化的方式将输出和错误消息写入日志文件,例如:
[STDOUT: 2011-01-17 14:53:55] <message>
[STDERR: 2011-01-17 14:53:56] <message>
Run Code Online (Sandbox Code Playgroud)
我的问题是,最恐怖的方式是什么?我想到了三个选择:
write方法.write.PIPE某种方式连接到自身.更新:参考测试脚本
我正在使用此脚本检查结果,保存为test.py:
#!/usr/bin/python
import sys
sys.stdout.write('OUT\n')
sys.stdout.flush()
sys.stderr.write('ERR\n')
sys.stderr.flush() …Run Code Online (Sandbox Code Playgroud) 我想捕获并显示我通过Python的子进程调用的进程的输出.
我以为我可以将我的文件类对象作为命名参数stdout和stderr传递
我可以看到它访问fileno属性 - 所以它正在对对象做一些事情.但是,write()永远不会调用该方法.我的方法是完全关闭还是我错过了什么?
class Process(object):
class StreamWrapper(object):
def __init__(self, stream):
self._stream = stream
self._buffer = []
def _print(self, msg):
print repr(self), msg
def __getattr__(self, name):
if not name in ['fileno']:
self._print("# Redirecting: %s" % name)
return getattr(self._stream, name)
def write(self, data):
print "###########"
self._buffer.append(data)
self._stream.write(data)
self._stream.flush()
def getBuffer(self):
return self._buffer[:]
def __init__(self, *args, **kwargs):
print ">> Running `%s`" % " ".join(args[0])
self._stdout = self.StreamWrapper(sys.stdout)
self._stderr = self.StreamWrapper(sys.stderr)
kwargs.setdefault('stdout', self._stdout)
kwargs.setdefault('stderr', self._stderr)
self._process = subprocess.Popen(*args, …Run Code Online (Sandbox Code Playgroud) 我正在编写一个与工作流管理器一起使用的包装类.我想以subprocess.Popen某种方式记录应用程序的输出(通过执行的子进程):
stdout孩子应该去一个日志文件和stdout父母的,stderr该子项应该转到不同的日志文件,但也应该转到stdout父项.即所有来自孩子的输出应该最终合并stdout(比如subprocess.Popen(..., stderr=subprocess.STDOUT),因此我可以保留stderr来自包装器本身的日志消息.另一方面,孩子的流应该转到不同的文件以允许单独的验证.
我尝试使用"Tee"帮助程序类将两个流(stdout和日志文件)绑定在一起,以便Tee.write写入两个流.但是,这不能传递给Popen因为"subprocess"使用OS级函数进行编写(参见http://bugs.python.org/issue1631).
我当前的解决方案(下面的代码片段,主要是从这里调整)的问题是输出stdout可能不会以正确的顺序出现.
我怎么能克服这个?或者我应该使用完全不同的方法?(如果我坚持下面的代码,我如何选择一个字节数的值os.read?)
import subprocess, select, sys, os
call = ... # set this
process = subprocess.Popen(call, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
logs = {process.stdout: open("out.log", "w"), process.stderr: open("err.log", "w")}
done = {process.stdout: False, process.stderr: False}
while (process.poll() is None) or (not all(done.values())):
ready = select.select([process.stdout, process.stderr], [], [])[0]
for …Run Code Online (Sandbox Code Playgroud) 我想开始一个python进程并将子进程错误消息记录到父脚本的日志记录对象.理想情况下,我希望将日志流统一到一个文件中.我能以某种方式访问日志记录类的输出流吗?我所知道的一个解决方案是使用proc日志进行日志记录.如下面的答案所述,我可以从proc.stdin和stderr读取,但我有重复的日志标头.我想知道是否有办法将日志记录类下面的文件描述符直接传递给子进程?
logging.basicConfig(filename="test.log",level=logging.DEBUG)
logging.info("Started")
procLog = open(os.path.expanduser("subproc.log"), 'w')
proc = subprocess.Popen(cmdStr, shell=True, stderr=procLog, stdout=procLog)
proc.wait()
procLog.flush()
Run Code Online (Sandbox Code Playgroud) python ×9
subprocess ×7
logging ×3
stderr ×2
stdout ×2
buffered ×1
iostream ×1
popen ×1
python-3.x ×1
stream ×1