如何在Python脚本中调用外部命令(就像我在Unix shell或Windows命令提示符下键入它一样)?
我正在使用python脚本作为流体动力学代码的驱动程序.当运行模拟时,我subprocess.Popen用来运行代码,从stdout和stderr收集输出到subprocess.PIPE---然后我可以打印(并保存到日志文件)输出信息,并检查是否有任何错误.问题是,我不知道代码是如何进展的.如果我直接从命令行运行它,它会给我输出关于它在什么时间迭代,什么时间,下一个时间步骤是什么等等的输出.
有没有办法既存储输出(用于记录和错误检查),还产生实时流输出?
我的代码的相关部分:
ret_val = subprocess.Popen( run_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True )
output, errors = ret_val.communicate()
log_file.write(output)
print output
if( ret_val.returncode ):
print "RUN failed\n\n%s\n\n" % (errors)
success = False
if( errors ): log_file.write("\n\n%s\n\n" % errors)
Run Code Online (Sandbox Code Playgroud)
最初我正在run_command通过管道,tee以便副本直接进入日志文件,并且流仍然直接输出到终端 - 但这样我就不能存储任何错误(对我的知识).
编辑:
临时解决方案:
ret_val = subprocess.Popen( run_command, stdout=log_file, stderr=subprocess.PIPE, shell=True )
while not ret_val.poll():
log_file.flush()
Run Code Online (Sandbox Code Playgroud)
然后,在另一个终端,运行tail -f log.txt(st log_file = 'log.txt').
我正在使用Python subprocess.communicate()来从一个运行大约一分钟的进程中读取stdout.
如何stdout以流式方式打印出该流程的每一行,以便我可以看到生成的输出,但在继续之前仍然阻止流程终止?
subprocess.communicate() 似乎立刻提供所有输出.
我正在寻找一种Python解决方案,它允许我将命令的输出保存在文件中,而不会将其从控制台中隐藏.
仅供参考:我问的是tee(作为Unix命令行实用程序)而不是Python intertools模块中具有相同名称的函数.
tee,在Windows下不可用)stderr而努力stdoutstderr = subprocess.STDOUT不起作用.以下是我发现的一些不完整的解决方案:
图http://blog.i18n.ro/wp-content/uploads/2010/06/Drawing_tee_py.png
#!/usr/bin/python
from __future__ import print_function
import sys, os, time, subprocess, io, threading
cmd = "python -E test_output.py"
from threading import Thread
class StreamThread ( Thread ):
def __init__(self, buffer):
Thread.__init__(self)
self.buffer = buffer
def run ( self ):
while 1:
line = self.buffer.readline()
print(line,end="") …Run Code Online (Sandbox Code Playgroud) 我想运行一个python脚本并捕获文本文件的输出以及想要在控制台上显示.
我想将它指定为python脚本本身的属性.不要echo "hello world" | tee test.txt每次都在命令提示符上使用该命令.
在脚本中我试过:
sys.stdout = open('log.txt','w')
Run Code Online (Sandbox Code Playgroud)
但是这并没有在屏幕上显示stdout输出.
我听说过记录模块,但是我无法使用该模块来完成这项工作.
我正在使用Popen调用一个shell脚本,该脚本不断将其stdout和stderr写入日志文件.有没有办法连续同时输出日志文件(到屏幕),或者让shell脚本同时写入日志文件和标准输出?
我基本上想在Python中做这样的事情:
cat file 2>&1 | tee -a logfile #"cat file" will be replaced with some script
Run Code Online (Sandbox Code Playgroud)
再次,这将stderr/stdout连接到tee,将它写入stdout和我的日志文件.
我知道如何在Python中将stdout和stderr写入日志文件.我被困在哪里是如何将这些复制回屏幕:
subprocess.Popen("cat file", shell=True, stdout=logfile, stderr=logfile)
Run Code Online (Sandbox Code Playgroud)
当然我可以做这样的事情,但有没有办法在没有tee和shell文件描述符重定向的情况下做到这一点?:
subprocess.Popen("cat file 2>&1 | tee -a logfile", shell=True)
Run Code Online (Sandbox Code Playgroud) 可能重复:
包装子进程'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) 我有一个python子进程,我正在尝试从中读取输出和错误流.目前我有它的工作,但我只能在读完stderr之后阅读stdout.这是它的样子:
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_iterator = iter(process.stdout.readline, b"")
stderr_iterator = iter(process.stderr.readline, b"")
for line in stdout_iterator:
# Do stuff with line
print line
for line in stderr_iterator:
# Do stuff with line
print line
Run Code Online (Sandbox Code Playgroud)
如您所见,stderrfor循环在stdout循环完成之前无法启动.如何修改它以便能够以正确的顺序读取这两行?
澄清:我仍然需要能够判断一条线是否来自stdout或者stderr因为我的代码中它们的处理方式不同.
我有一个命令行工具(实际上是几个),我正在用Python编写包装器.
该工具通常使用如下:
$ path_to_tool -option1 -option2 > file_out
Run Code Online (Sandbox Code Playgroud)
用户将输出写入file_out,并且还能够在工具运行时查看该工具的各种状态消息.
我想复制此行为,同时还将stderr(状态消息)记录到文件中.
我有的是这个:
from subprocess import call
call(['path_to_tool','-option1','option2'], stdout = file_out, stderr = log_file)
Run Code Online (Sandbox Code Playgroud)
除了stderr没有写入屏幕之外,这工作正常.我当然可以添加代码来将log_file的内容打印到屏幕上,但是用户将在完成所有操作后看到它,而不是在它发生时.
总结一下,期望的行为是:
我有一种感觉,我要么错过了一些非常简单的东西,要么这比我想象的要复杂得多......感谢您的帮助!
编辑:这只需要在Linux上工作.
是否可以修改以下代码以从'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 ×9
subprocess ×9
stderr ×3
popen ×2
shell ×2
stdout ×2
command ×1
logging ×1
python-2.7 ×1
python-3.x ×1
tee ×1
terminal ×1