Python论坛  - 讨论区

标题:[python-chinese] 如何非阻塞地读取子进程的输出

2005年06月29日 星期三 13:51

Hong Yuan hongyuan at homemaster.cn
Wed Jun 29 13:51:51 HKT 2005

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

例如,假设外部程序是以下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下。

-- 
HONG Yuan

大管家网上建材超市
http://www.homemaster.cn


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月29日 星期三 14:08

Neo Chan (netkiller) neo.chen at achievo.com
Wed Jun 29 14:08:38 HKT 2005

Skipped content of type multipart/mixed-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3066 bytes
Desc: not available
Url : http://lists.exoweb.net/pipermail/python-chinese/attachments/20050629/e587cf13/smime.bin

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月29日 星期三 14:27

nEO gentoo.cn at gmail.com
Wed Jun 29 14:27:48 HKT 2005

你这里不应该用read
应该用readline

2005/6/29, Hong Yuan <hongyuan at homemaster.cn>:
> 我在程序中需要启动一个外部命令并读取该命令的输出。问题是这个外部命令在产
> 生第一部分输出后要停顿很长时间,而我并不想等到外部命令全部结束再去读取它
> 的输出,而想先得到第一部分的输出。
> 
> 例如,假设外部程序是以下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下。
> 
> --
> HONG Yuan
> 
> 大管家网上建材超市
> http://www.homemaster.cn
> 
> _______________________________________________
> python-chinese list
> python-chinese at lists.python.cn
> http://python.cn/mailman/listinfo/python-chinese
> 


-- 
I'm the one, powered by nEO

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月29日 星期三 14:32

Hong Yuan hongyuan at homemaster.cn
Wed Jun 29 14:32:57 HKT 2005

select用于socket本来就没有问题的,但对于进程间的管道好像是有问题的。

Neo Chan (netkiller) wrote:

> 
>大同小意..改改就成..自己研究去吧.
>
>import select
>import socket
>import time
>
>PORT = 8037
>
>TIME1970 = 2208988800L
>
>service = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>service.bind(("", PORT))
>service.listen(1)
>
>print "listening on port", PORT
>
>while 1:
>    is_readable = [service]
>    is_writable = []
>    is_error = []
>    r, w, e = select.select(is_readable, is_writable, is_error, 1.0)
>    if r:
>        channel, info = service.accept()
>        print "connection from", info
>        t = int(time.time()) + TIME1970
>        t = chr(t>>24&255) + chr(t>>16&255) + chr(t>>8&255) + chr(t&255)
>        channel.send(t) # send timestamp
>        channel.close() # disconnect
>    else:
>        print "still waiting"
>
>Neo Chan (netkiller)
>Best Regards, 73! de BG7NYT
>Amateur Radio Callsign: BG7NYT
>
>注:我这里上不了网,请不要发URL给我,如果方便请附件发给我
>
>
>-----Original Message-----
>From: python-chinese-bounces at lists.python.cn [mailto:python-chinese-bounces at lists.python.cn] On Behalf Of Hong Yuan
>Sent: Wednesday, June 29, 2005 1:52 PM
>To: python-chinese at lists.python.cn
>Subject: [python-chinese] 如何非阻塞地读取子进程的输出
>
>我在程序中需要启动一个外部命令并读取该命令的输出。问题是这个外部命令在产
>生第一部分输出后要停顿很长时间,而我并不想等到外部命令全部结束再去读取它
>的输出,而想先得到第一部分的输出。
>
>例如,假设外部程序是以下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下。
>
>--
>HONG Yuan
>
>大管家网上建材超市
>http://www.homemaster.cn
>
>_______________________________________________
>python-chinese list
>python-chinese at lists.python.cn
>http://python.cn/mailman/listinfo/python-chinese
>  
>
>_______________________________________________
>python-chinese list
>python-chinese at lists.python.cn
>http://python.cn/mailman/listinfo/python-chinese
>  
>

-- 
HONG Yuan

大管家网上建材超市
http://www.homemaster.cn


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月29日 星期三 15:01

Hong Yuan hongyuan at homemaster.cn
Wed Jun 29 15:01:23 HKT 2005

问题不在于用readline还是read,无论用哪个,都会将当前进程block到外部程序 
完全执行完才会继续。

可能是对管道、缓冲什么的需要有什么设置select才能有正确的返回。

nEO wrote:

>你这里不应该用read
>应该用readline
>
>2005/6/29, Hong Yuan <hongyuan at homemaster.cn>:
>  
>
>>--
>>HONG Yuan
>>
>>大管家网上建材超市
>>http://www.homemaster.cn
>>
>>_______________________________________________
>>python-chinese list
>>python-chinese at lists.python.cn
>>http://python.cn/mailman/listinfo/python-chinese
>>
>>    
>>
>
>
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>python-chinese list
>python-chinese at lists.python.cn
>http://python.cn/mailman/listinfo/python-chinese
>  
>

-- 
HONG Yuan

大管家网上建材超市
http://www.homemaster.cn


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月29日 星期三 19:19

shhgs shhgs.efhilt at gmail.com
Wed Jun 29 19:19:06 HKT 2005

On 6/29/05, Hong Yuan <hongyuan at homemaster.cn> wrote:
> 我在程序中需要启动一个外部命令并读取该命令的输出。问题是这个外部命令在产
> 生第一部分输出后要停顿很长时间,而我并不想等到外部命令全部结束再去读取它
> 的输出,而想先得到第一部分的输出。
> 
> 例如,假设外部程序是以下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]

select的作用是查看三个流的集合,发现其中的可读,可写,以及有错误报出的流。

你这里的问题,一是没有返回这个集合,所以它被当作垃圾回收了。第二select是非阻塞的,所以返回之后,它就等着执行下一句,也就是pout.read()了。这当然要等程序执行完毕才能运行。所以我觉得应该这么写:

while 1 :
  i,o,e = select.select([pout], [], [], timeout)
    if i :
        print i[0].read()

> pout.read()
> 
> 根据文档select应该等到pout有可读取的内容(即前500个'hello')时就返回,但实
> 际情况是它要一直到test.py全部执行完毕才返回可读的内容。
> 
> 谁知道这段代码应该如何正确书写?代码运行在Linux下。

顺便说一句,Linux下可以,Windows下不行。Windows的select只支持socket。

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月29日 星期三 19:50

hw1979 hw1979 at gmail.com
Wed Jun 29 19:50:03 HKT 2005

你也可以继承一下StringIO,把输出重定向到这里,然后在你需要的时候抛出异常.

shhgs 写道:

>On 6/29/05, Hong Yuan <hongyuan at homemaster.cn> wrote:
>  
>
>>我在程序中需要启动一个外部命令并读取该命令的输出。问题是这个外部命令在产
>>生第一部分输出后要停顿很长时间,而我并不想等到外部命令全部结束再去读取它
>>的输出,而想先得到第一部分的输出。
>>
>>例如,假设外部程序是以下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]
>>    
>>
>
>select的作用是查看三个流的集合,发现其中的可读,可写,以及有错误报出的流。
>
>你这里的问题,一是没有返回这个集合,所以它被当作垃圾回收了。第二select是非阻塞的,所以返回之后,它就等着执行下一句,也就是pout.read()了。这当然要等程序执行完毕才能运行。所以我觉得应该这么写:
>
>while 1 :
>  i,o,e = select.select([pout], [], [], timeout)
>    if i :
>        print i[0].read()
>
>  
>
>>pout.read()
>>
>>根据文档select应该等到pout有可读取的内容(即前500个'hello')时就返回,但实
>>际情况是它要一直到test.py全部执行完毕才返回可读的内容。
>>
>>谁知道这段代码应该如何正确书写?代码运行在Linux下。
>>    
>>
>
>顺便说一句,Linux下可以,Windows下不行。Windows的select只支持socket。
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>python-chinese list
>python-chinese at lists.python.cn
>http://python.cn/mailman/listinfo/python-chinese
>  
>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月30日 星期四 10:24

Hong Yuan hongyuan at homemaster.cn
Thu Jun 30 10:24:33 HKT 2005

谢谢大家的帮助。最后下面这段代码工作得很好:

import os, fcntl, select

cmd = 'python test.py'

timeout = 2
pin, pout = os.popen2(cmd)

pout = pout.fileno()
flags = fcntl.fcntl(pout, fcntl.F_GETFL)
fcntl.fcntl(pout, fcntl.F_SETFL, flags | os.O_NONBLOCK)

while 1:
    i,o,e = select.select([pout], [], [], timeout)
    if i :
        buf = os.read(pout, 1024)
        if buf:
            print buf
        else:
            break

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

-- 
HONG Yuan

大管家网上建材超市
http://www.homemaster.cn


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年06月30日 星期四 17:54

nEO gentoo.cn at gmail.com
Thu Jun 30 17:54:31 HKT 2005

这段代码工作正常
但是还是没明白为什么我的那段代码你不能运行


2005/6/30, Hong Yuan <hongyuan at homemaster.cn>:
> 
> 谢谢大家的帮助。最后下面这段代码工作得很好:
> 
> import os, fcntl, select
> 
> cmd = 'python test.py'
> 
> timeout = 2
> pin, pout = os.popen2(cmd)
> 
> pout = pout.fileno()
> flags = fcntl.fcntl(pout, fcntl.F_GETFL)
> fcntl.fcntl(pout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
> 
> while 1:
> i,o,e = select.select([pout], [], [], timeout)
> if i :
> buf = os.read(pout, 1024)
> if buf:
> print buf
> else:
> break
> 
> 由fcntl函数将文件设为非阻塞模式,用select来判断是否有数据可读,然后用
> os.read读取当前可读的所有数据。
> 
> --
> HONG Yuan
> 
> 大管家网上建材超市
> http://www.homemaster.cn
> 
> _______________________________________________
> python-chinese list
> python-chinese at lists.python.cn
> http://python.cn/mailman/listinfo/python-chinese
> 



-- 
I'm the one, powered by nEO
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.exoweb.net/pipermail/python-chinese/attachments/20050630/d82856b3/attachment.html

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号