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
- 由fcntl函数将文件设为非阻塞模式,用select来判断是否有数据可读,然后用os.read读取当前可读的所有数据。