Ing*_*her 175 python subprocess
要从我的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
tok*_*and 236
您可以在命令输出后立即使用iter处理线路:lines = iter(fd.readline, "").这是一个显示典型用例的完整示例(感谢@jfs帮助):
from __future__ import print_function # Only Python 2.x
import subprocess
def execute(cmd):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
for stdout_line in iter(popen.stdout.readline, ""):
yield stdout_line
popen.stdout.close()
return_code = popen.wait()
if return_code:
raise subprocess.CalledProcessError(return_code, cmd)
# Example
for path in execute(["locate", "a"]):
print(path, end="")
Run Code Online (Sandbox Code Playgroud)
Ing*_*her 81
好吧,我设法解决它没有线程(任何建议为什么使用线程会更好被赞赏)通过使用此问题的片段在运行时拦截子进程的stdout
def execute(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# Poll process for new output until finished
while True:
nextline = process.stdout.readline()
if nextline == '' and process.poll() is not None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = process.communicate()[0]
exitCode = process.returncode
if (exitCode == 0):
return output
else:
raise ProcessException(command, exitCode, output)
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 59
一旦在Python 3中刷新stdout缓冲区,就逐行打印子进程'输出:
from subprocess import Popen, PIPE, CalledProcessError
with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
print(line, end='') # process line here
if p.returncode != 0:
raise CalledProcessError(p.returncode, p.args)
Run Code Online (Sandbox Code Playgroud)
注意:您不需要p.poll()- 当到达eof时,循环结束.并且您不需要iter(p.stdout.readline, '')- 预读错误在Python 3中得到修复.
另请参阅Python:从subprocess.communicate()读取流输入.
ari*_*ing 19
当您只想print输出时,实际上有一种非常简单的方法可以做到这一点:
import subprocess
import sys
def execute(command):
subprocess.check_call(command, stdout=sys.stdout, stderr=subprocess.STDOUT)
Run Code Online (Sandbox Code Playgroud)
在这里,我们只是将子流程指向我们自己的stdout,并使用现有的成功或异常 api。
小智 7
在Python> = 3.5中使用subprocess.run对我有效:
import subprocess
cmd = 'echo foo; sleep 1; echo foo; sleep 2; echo foo'
subprocess.run(cmd, shell=True)
Run Code Online (Sandbox Code Playgroud)
(在执行期间获取输出也可以在没有的情况下使用shell=True)
https://docs.python.org/3/library/subprocess.html#subprocess.run
对于尝试回答这个问题以从 Python 脚本中获取标准输出的任何人,请注意 Python 缓冲其标准输出,因此可能需要一段时间才能看到标准输出。
这可以通过在目标脚本中的每个 stdout 写入后添加以下内容来纠正:
sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)
小智 5
@tokland
尝试了你的代码并更正了3.4和windows dir.cmd是一个简单的dir命令,保存为cmd文件
import subprocess
c = "dir.cmd"
def execute(command):
popen = subprocess.Popen(command, stdout=subprocess.PIPE,bufsize=1)
lines_iterator = iter(popen.stdout.readline, b"")
while popen.poll() is None:
for line in lines_iterator:
nline = line.rstrip()
print(nline.decode("latin"), end = "\r\n",flush =True) # yield line
execute(c)
Run Code Online (Sandbox Code Playgroud)
如果有人想从两个读stdout和stderr在同一时间使用线程,这是我想出了:
import threading
import subprocess
import Queue
class AsyncLineReader(threading.Thread):
def __init__(self, fd, outputQueue):
threading.Thread.__init__(self)
assert isinstance(outputQueue, Queue.Queue)
assert callable(fd.readline)
self.fd = fd
self.outputQueue = outputQueue
def run(self):
map(self.outputQueue.put, iter(self.fd.readline, ''))
def eof(self):
return not self.is_alive() and self.outputQueue.empty()
@classmethod
def getForFd(cls, fd, start=True):
queue = Queue.Queue()
reader = cls(fd, queue)
if start:
reader.start()
return reader, queue
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdoutReader, stdoutQueue) = AsyncLineReader.getForFd(process.stdout)
(stderrReader, stderrQueue) = AsyncLineReader.getForFd(process.stderr)
# Keep checking queues until there is no more output.
while not stdoutReader.eof() or not stderrReader.eof():
# Process all available lines from the stdout Queue.
while not stdoutQueue.empty():
line = stdoutQueue.get()
print 'Received stdout: ' + repr(line)
# Do stuff with stdout line.
# Process all available lines from the stderr Queue.
while not stderrQueue.empty():
line = stderrQueue.get()
print 'Received stderr: ' + repr(line)
# Do stuff with stderr line.
# Sleep for a short time to avoid excessive CPU use while waiting for data.
sleep(0.05)
print "Waiting for async readers to finish..."
stdoutReader.join()
stderrReader.join()
# Close subprocess' file descriptors.
process.stdout.close()
process.stderr.close()
print "Waiting for process to exit..."
returnCode = process.wait()
if returnCode != 0:
raise subprocess.CalledProcessError(returnCode, command)
Run Code Online (Sandbox Code Playgroud)
我只是想分享这个,因为我最终在这个问题上尝试做类似的事情,但没有一个答案解决了我的问题。希望它可以帮助某人!
请注意,在我的用例中,外部进程会杀死我们Popen().
要回答原始问题,IMO 的最佳方法是将子进程stdout直接重定向到您的程序stdout(可选,可以对 执行相同的操作stderr,如下例所示)
p = Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
p.communicate()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
155982 次 |
| 最近记录: |