Chinaunix

标题: [求助]Python管道即时读取输出问题 [打印本页]

作者: wn0112    时间: 2013-05-29 17:07
标题: [求助]Python管道即时读取输出问题
本帖最后由 wn0112 于 2013-05-29 17:07 编辑
  1. import subprocess, time   
  2. pipe = subprocess.Popen('myapp.exe file.ext', stdout=subprocess.PIPE)
  3. while 1:     
  4.     pipe.stdout.readline()     
  5.     time.sleep(0.2)
复制代码
在myapp.exe执行过程中会产生许多Log,我是想能够即时地把Log取出来显示在界面上。
但是发现read(), readlines(), communicate()都是会等待myapp.exe执行完毕,再读取所有输出,达不到“即时”的效果。
现在是用了一个等待循环,每0.2秒用readline()来读取一行显示在界面。
请问有没有更好的方法?更智能点的
作者: jeppeter    时间: 2013-05-30 06:26
回复 1# wn0112


    这个问题出在你的myapp.exe上面,这里在打印输出的时候,没有用FLUSH。如果用了,就没有你说的那个问题。
作者: wn0112    时间: 2013-05-30 10:43
jeppeter 发表于 2013-05-30 06:26
回复 1# wn0112

不是的,myapp.exe 是可以即时输出Log信息到终端或管道的
作者: jeppeter    时间: 2013-05-30 10:49
回复 3# wn0112


    这个,我测试过,我用python的程序测试,如果不加sys.stdout.flush(),那就是最后到程序结束的时候才有输出。但,如果加了flush,就会立刻输出了。
作者: wn0112    时间: 2013-05-30 11:03
本帖最后由 wn0112 于 2013-05-30 11:09 编辑
jeppeter 发表于 2013-05-30 10:49
回复 3# wn0112

如果只是 “即时” 输出到终端的话(也就是sys.stdout)这样就可以了,是没问题的

  1. import subprocess
  2. pipe = subprocess.Popen('myapp.exe file.ext')

复制代码
但现在是要取得输出内容,就用了管道,除非用readline(),read(), communicate()都不能“即时”

你是说这样用吗?也是不行的,要等myapp.exe结束才有输出

  1. import subprocess, time   
  2. pipe = subprocess.Popen('myapp.exe file.ext', stdout=subprocess.PIPE)
  3. while 1:
  4.     pipe.stdout.flush()   
  5.     pipe.stdout.read()     
  6.     time.sleep(0.2)
复制代码
如果在read()里设置字节数,且字节数小于实际内容,也可以即时,但如果大于实际内容也不会即时了,好像要等达到字节数或结束才输出

  1. import subprocess, time   
  2. pipe = subprocess.Popen('myapp.exe file.ext', stdout=subprocess.PIPE)
  3. while 1:  
  4.     pipe.stdout.read(5)     
  5.     time.sleep(0.2)
复制代码

作者: jeppeter    时间: 2013-05-30 11:23
回复 5# wn0112


    你理解错了,不是在你的父程序里做FLUSH,而是你的myapp.exe的输出的时候用FLUSH,我测试过,在父程序,确实会出现你说的问题,而在myapp.exe 输出的时候flush,是不会出现这样的问题的。
作者: wn0112    时间: 2013-05-30 12:16
jeppeter 发表于 2013-05-30 11:23
回复 5# wn0112

myapp.exe是第三方程序,不是我写的,它没有flush, 你是这个意思??
应该不关myapp.exe的事,我用tcl脚本实现同样的事情,就可以得到即时输出, 用的是read方式,不是readline
作者: jeppeter    时间: 2013-05-30 12:49
回复 7# wn0112


    你说了,是read而不是readline,这两种方法是有差别的。不如你采用read的方法。
作者: laike9m    时间: 2013-05-30 12:56
试试把读取管道内容的代码放在另一个线程里面呢?我以前在某个需要输出即时进度的地方这样做过。
作者: 106033177    时间: 2013-05-30 13:06
回复 1# wn0112
subprocess.Popen('myapp.exe file.ext',bufsize=0, stdout=subprocess.PIPE) 

   
作者: wn0112    时间: 2013-05-30 14:11
jeppeter 发表于 2013-05-30 12:49
回复 7# wn0112

说的就是read()不能即时啊……只有readline()加个延时循环才能达到目的,现在是想寻求更好的方法……
作者: wn0112    时间: 2013-05-30 14:19
laike9m 发表于 2013-05-30 12:56
试试把读取管道内容的代码放在另一个线程里面呢?我以前在某个需要输出即时进度的地方这样做过。

怎么放呢?

我的问题是:

作者: wn0112    时间: 2013-05-30 14:20
106033177 发表于 2013-05-30 13:06
回复 1# wn0112
subprocess.Popen('myapp.exe file.ext',bufsize=0, stdout=subprocess.PIPE) 

bufsize=0试过了
使用pipe.stdout.read() 还是会等待myapp.exe结束才读取全部
作者: wn0112    时间: 2013-06-14 18:23
这个可以
  1. import subprocess
  2. pipe = subprocess.Popen('myapp.exe file.ext', stdout=subprocess.PIPE)
  3. for line in iter(pipe.stdout.readline, ''):     
  4.     print line
复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2