TableOfContents

2005-06-29 如何非阻塞地读取子进程的输出

[wiki:PyCNmail/2005-June/011936.html 如何非阻塞地读取子进程的输出] 引发

发件人: Hong Yuan <[email protected]>
回复: [email protected]
收件人: [email protected]
日期: 2005-6-29 下午1:51

问题

{{{我在程序中需要启动一个外部命令并读取该命令的输出。问题是这个外部命令在产 生第一部分输出后要停顿很长时间,而我并不想等到外部命令全部结束再去读取它 的输出,而想先得到第一部分的输出。

例如,假设外部程序是以下python代码:

test.py: import sys, time print 'hello'*500 sys.stdout.flush() time.sleep(100) print 'world'*500

我希望在自己的程序中设置一个timeout,读取外部进程在这个timeout时间前的所 有输出,即前500个'hello'。我的程序是这样写的:

import os, select cmd = 'python test.py' pin, pout = os.popen2(cmd) select.select([pout], [], [], timeout)[0] pout.read()

根据文档select应该等到pout有可读取的内容(即前500个'hello')时就返回,但实 际情况是它要一直到test.py全部执行完毕才返回可读的内容。

谁知道这段代码应该如何正确书写?代码运行在Linux下。 }}}

讨论

成果

   1 import os, fcntl, select
   2 
   3 cmd = 'python test.py'
   4 
   5 timeout = 2
   6 pin, pout = os.popen2(cmd)
   7 
   8 pout = pout.fileno()
   9 flags = fcntl.fcntl(pout, fcntl.F_GETFL)
  10 fcntl.fcntl(pout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
  11 
  12 while 1:
  13    i,o,e = select.select([pout], [], [], timeout)
  14    if i :
  15        buf = os.read(pout, 1024)
  16        if buf:
  17            print buf
  18        else:
  19            break