我正在尝试为命令行程序(svnadmin verify)编写一个包装器脚本,它将为操作显示一个很好的进度指示器.这要求我能够在输出后立即查看包装程序的每一行输出.
我想我只是执行程序使用subprocess.Popen,使用stdout=PIPE,然后读取每一行,并相应地对其进行操作.但是,当我运行以下代码时,输出似乎在某处缓冲,导致它出现在两个块中,第1行到第332行,然后是333到439(输出的最后一行)
from subprocess import Popen, PIPE, STDOUT
p = Popen('svnadmin verify /var/svn/repos/config', stdout = PIPE,
stderr = STDOUT, shell = True)
for line in p.stdout:
print line.replace('\n', '')
Run Code Online (Sandbox Code Playgroud)
稍微查看子进程的文档后,我发现bufsize参数为Popen,所以我尝试将bufsize设置为1(缓冲每行)和0(无缓冲区),但这两个值似乎都没有改变行的传递方式.
此时我开始掌握吸管,所以我编写了以下输出循环:
while True:
try:
print p.stdout.next().replace('\n', '')
except StopIteration:
break
Run Code Online (Sandbox Code Playgroud)
但得到了相同的结果.
是否有可能获得使用子进程执行的程序的"实时"程序输出?Python中是否有其他选项可以向前兼容(不是exec*)?
我正在使用Python subprocess.communicate()来从一个运行大约一分钟的进程中读取stdout.
如何stdout以流式方式打印出该流程的每一行,以便我可以看到生成的输出,但在继续之前仍然阻止流程终止?
subprocess.communicate() 似乎立刻提供所有输出.
我想以下列方式使用子进程模块:
stdout(或者stderr,或者两者一起或分别捕获)我已经用Popen创建了进程,但是如果我使用communication(),那么一旦进程终止,数据就会立刻出现在我面前.
如果我创建一个单独的线程,做了阻塞readline()的myprocess.stdout(使用stdout = subprocess.PIPE)我不明白这种方法的任何行或者,直到进程终止.(无论我设置为bufsize)
有没有办法解决这个不可怕的问题,并且在多个平台上运行良好?
如果这是我的子流程:
import time, sys
for i in range(200):
sys.stdout.write( 'reading %i\n'%i )
time.sleep(.02)
Run Code Online (Sandbox Code Playgroud)
这是控制和修改子进程输出的脚本:
import subprocess, time, sys
print 'starting'
proc = subprocess.Popen(
'c:/test_apps/testcr.py',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE )
print 'process created'
while True:
#next_line = proc.communicate()[0]
next_line = proc.stdout.readline()
if next_line == '' and proc.poll() != None:
break
sys.stdout.write(next_line)
sys.stdout.flush()
print 'done'
Run Code Online (Sandbox Code Playgroud)
为什么readline和communicate等待,直到程序完成后运行?有没有一种简单的方法来传递(和修改)子进程'stdout实时?
顺便说一下,我已经看过了,但是我不需要记录功能(并且没有太多的了解它).
我在Windows XP上.
我看了很多问题,但仍然无法弄清楚这一点.我正在使用PyQt,我希望运行ffmpeg -i file.mp4 file.avi并获取输出,因为我可以创建一个进度条.
我看过这些问题: ffmpeg可以显示进度条吗? 从子进程实时捕获stdout
我能够使用以下代码查看rsync命令的输出:
import subprocess, time, os, sys
cmd = "rsync -vaz -P source/ dest/"
p, line = True, 'start'
p = subprocess.Popen(cmd,
shell=True,
bufsize=64,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
for line in p.stdout:
print("OUTPUT>>> " + str(line.rstrip()))
p.stdout.flush()
Run Code Online (Sandbox Code Playgroud)
但是当我更改命令时,ffmpeg -i file.mp4 file.avi我没有收到任何输出.我猜这与stdout/output缓冲有关,但是我不知道如何读取看起来像的行
frame= 51 fps= 27 q=31.0 Lsize= 769kB time=2.04 bitrate=3092.8kbits/s
Run Code Online (Sandbox Code Playgroud)
我可以用来计算进度.
有人可以告诉我一个如何从ffmpeg获取此信息到python的示例,无论是否使用PyQt(如果可能)
编辑: 我最终使用jlp的解决方案,我的代码看起来像这样:
#!/usr/bin/python
import pexpect
cmd = 'ffmpeg -i file.MTS file.avi'
thread = pexpect.spawn(cmd)
print "started %s" % cmd …Run Code Online (Sandbox Code Playgroud) 同样,同样的问题.
原因是 - 阅读以下内容后仍然无法使其正常工作:
我的情况是我有一个用C编写的控制台应用程序,让我们在循环中采用这个代码:
tmp = 0.0;
printf("\ninput>>");
scanf_s("%f",&tmp);
printf ("\ninput was: %f",tmp);
Run Code Online (Sandbox Code Playgroud)
它不断读取一些输入并写入一些输出.
我与它交互的python代码如下:
p=subprocess.Popen([path],stdout=subprocess.PIPE,stdin=subprocess.PIPE)
p.stdin.write('12345\n')
for line in p.stdout:
print(">>> " + str(line.rstrip()))
p.stdout.flush()
Run Code Online (Sandbox Code Playgroud)
到目前为止,每当我读取表单时,p.stdout它总是等待,直到进程终止然后输出一个空字符串.我尝试了很多东西 - 但结果仍然相同.
我尝试过Python 2.6和3.1,但版本没关系 - 我只需要让它在某个地方工作.
我正在尝试创建一个将在服务器上远程执行的执行环境/ shell,它将stdout,err,流入套接字以在浏览器中呈现.我目前已经尝试过使用subprocess.runa 的方法PIPE.问题是我在进程完成后得到了stdout.我想要实现的是获得逐行,伪终端类型的实现.
我目前的实施
test.py
def greeter():
for _ in range(10):
print('hello world')
greeter()
Run Code Online (Sandbox Code Playgroud)
并在壳中
>>> import subprocess
>>> result = subprocess.run(['python3', 'test.py'], stdout=subprocess.PIPE)
>>> print(result.stdout.decode('utf-8'))
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
Run Code Online (Sandbox Code Playgroud)
如果我尝试尝试这个简单的实现pty,如何做到这一点?
我想读一下子进程在执行时写入stderr的内容.
但是,当我使用我编写的这个脚本时,stderr似乎没有任何东西供我阅读,直到子进程退出.
#!/usr/bin/env python2
import sys
from subprocess import Popen, PIPE, STDOUT
if len(sys.argv) < 2:
print "Please provide a command"
sys.exit(1)
sub = Popen(sys.argv[1:], stdout=PIPE, stderr=STDOUT)
for i, line in enumerate(sub.stdout):
sys.stdout.write("%d: %s" % (i, line))
Run Code Online (Sandbox Code Playgroud)
编辑:
好的,我现在离得更近了.如果我指定要读取的字节数,则克服缓冲.
#!/usr/bin/env python2
import sys
from subprocess import Popen, PIPE, STDOUT
if len(sys.argv) < 2:
print "Please provide a command"
sys.exit(1)
sub = Popen(sys.argv[1:], stdout=PIPE, stderr=STDOUT)
i = 0
while sub.poll() is None:
line = sub.stdout.read(64)
line.strip("\b")
sys.stdout.write("%d: %s\n" % (i, line)) …Run Code Online (Sandbox Code Playgroud) 我想运行一个系统进程,拦截输出,并在Python脚本中逐行实时修改它.
我最好的尝试,等待打印前完成的过程,是:
#!/usr/bin/env python
import subprocess
cmd = "waitsome.py"
proc = subprocess.Popen(cmd, shell=True, bufsize=256, stdout=subprocess.PIPE)
for line in proc.stdout:
print ">>> " + line.rstrip()
Run Code Online (Sandbox Code Playgroud)
脚本waitsome.py只需每半秒打印一行:
#!/usr/bin/env python
import time
from sys import stdout
print "Starting"
for i in range(0,20):
time.sleep(0.5)
print "Hello, iteration", i
stdout.flush()
Run Code Online (Sandbox Code Playgroud)
是否有一个简单的解决方案subprocess允许实时迭代输出?我必须使用线程吗?
曾几何时,我用Perl编写脚本,这是小菜一碟:
open(CMD, "waitsome.py |");
while (<CMD>) {
print ">>> $_";
}
close(CMD);
Run Code Online (Sandbox Code Playgroud)