python select模块.select实现非阻塞socket,Popen等(特别在 Unix 下,它还可以用于管道)

Python类库中文翻译:select — 等待 I/O 完成

select — Waiting for I/O completion

This module provides access to the select() and poll() functions available in most operating systems. Note that on  Windows , it only works for sockets; on other operating systems, it also works for other file types (in particular, on Unix, it works on pipes). It cannot be u sed  on regular files to determine whether a file has grown since it was last read.
这个模块提供的 select() 和 poll() 方法可用于大部分 操作系统 。注意:在  Win dows 下,它只能用于 sockets ;在其他 系统 下,它也可以用于其他类型(特别在 Unix 下,它还可以用于管道)。它不能用来确定是否完成上次的对普通 文件 执行的读取操作。

The module defines the following:
这个模块定义下列内容:

exception error
异常错误
The exception raised when an error occurs. The accompanying value is a pair containing the numeric error code from errno and the corresponding string, as would be printed by the C function perror().
在发生错误将引发异常。accompanying 值包含错误代码和错误描述文本,用于使用 C 程序 perror() 打印。

poll( )
(Not supported by all operating systems.) Returns a polling object, which supports registering and unregistering file descriptors, and then polling them for I/O events; see section 15.1.1 below for the methods supported by polling objects.

select( iwtd, owtd, ewtd[, timeout])
This is a straightforward interface to the Unix select() system call. The first three arguments are sequences of `waitable objects’: either integers representing file descriptors or objects with a parameterless method named fileno() returning such an integer. The three sequences of waitable objects are for input, output and `exceptional conditions’, respectively. Empty sequences are allowed, but acceptance of three empty sequences is platform-dependent. (It is known to work on Unix but not on Windows.) The optional timeout argument specifies a time-out as a floating point number in seconds. When the timeout argument is omitted the function blocks until at least one file descriptor is ready. A time-out value of zero specifies a poll and never blocks.
这对于 Ubix 系统调用 select() 来说是一个简单接口。前三个参数是‘等待对象’;????。这三个参数分别按顺序等待输入、输出输出和异常状态。允许空数组,但是是否允许三个空序列依赖于 平台 。(已知支持 Unix 但是不支持 Windows。)timeout 参数接受浮点数表示的秒。如果省略 timeout 着阻塞到至少一个文件描述符准备就绪。timeout 为0表示从不阻塞。
译者注:在对方关闭连接的情况下(CLOSE_WAIT状态)会立即返回,并且处于可读列表里面。但是却会立即读到0长度的 数据 。建议在检测到连续多次读到0长度数据时关闭连接。

The return value is a triple of lists of objects that are ready: subsets of the first three arguments. When the time-out is reached without a file descriptor becoming ready, three empty lists are returned.
返回值是包含前三个参数里面已准备就绪的对象的3个列表.如果已经超时但是并没有对象准备就绪,那么返回3个空列表

Among the acceptable object types in the sequences are Python file objects (e.g. sys.stdin, or objects returned by open() or os.popen()), socket objects returned by socket.socket().You may also define a wrapper class yourself, as long as it has an appropriate fileno() method (that really returns a file descriptor, not just a random integer). Note: File objects on Windows are not acceptable, but sockets are. On Windows, the underlying select() function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.
接受的对象类型按次序是 Python 文件对象(例如:sys.stdin 或者 open()或os.popen()返回的对象)或者socket.socket()返回的socket对象。你也可以定义一个类,只要它包含恰当的 fileno() 方法(它其实范围文件描述符,不要只是返回随机数)注意:windows 不接受文件对象,但是接受 sockets。在 windows 下 select() 程序隐式使用 WinSock 库,WinSock 并不支持文件对象句柄。

select.select(rlist, wlist, xlist[, timeout])

> 平台依赖性:

 Windows只支持socket作为fd,不支持文件的fd

 Linux 和Unix平台都支持

> 输入的文件描述符号可以为如下几种情况:

python file objects: 

              1. sys.stdin  

              2. open()   或者 os.popen()

              3. socket.socket()

              4. 其他可以调用fileno()的对象返回的文件描述符号(这个是真实的 fd,不仅仅是一个随机整数)


> 前三个参数是 ‘waitable objects’的序列,要么是整数代表的fd,或者是由fileno()返回的对象才能作为三个序列的元素

rlist: wait until ready for reading
wlist: wait until ready for writing
xlist: wait for an “exceptional condition” (see the manual page for what your system considers such a condition)

三个参数是否全为空是平台相关的,Unix系统是可以全为空的,Windows不能全为空.

Unix全为空的话,可以作为定时器用了。

> timeout 参数

timeout参数是浮点数代表的参数,单位是seconds

timeout参数省略(默认为None),则代表永远block直到有一个fd准备好。

timeout = 0, 代表不会block,或者(specifies a poll)

> return 参数

返回值为三个list,包含三个已经准备好的fd列表(不会超过输入三个参数)。

当timeout后还没有fd准备好,则返回三个空列表([],[],[])

python 的 List Comprehensions语法:

这个语法的目的是用于创建列表,其他相似的语法还有(map,filter, zip 和 lambda)



1.使用select实现非阻塞socket

-*- coding: cp936 -*-
"""
非阻塞socket的使用(此程序在ubuntu linux和windows xp上测试,Windows可以支持select.select)
监控socket的三个list:in/out/err
程序以5000ms的时间长度为间隔,如果有客户端的请求,接收连接并进行显示;如果没有的话,
每隔5000ms显示一次"
no data coming"
"
""
import socket,select

host = ""
port = 50000

= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen(5)
while 1:
     infds,outfds,errfds = select.select([s,],[],[],5)
     # 如果infds状态改变,进行处理,否则不予理会
    if len(infds) != 0:
         clientsock,clientaddr = s.accept()
         buf = clientsock.recv(8196)
        if len(buf) != 0:
                print (buf)
         clientsock.close()

    print "no data coming"

2.客户端程序与poll客户端基本一致,仅用来发送一字符串

-*- coding: cp936 -*-
"""
向服务器端发送字符串
"
""
import socket,select

host = "localhost"
port = 50000

= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))

s.send("coming from select client")
s.close()


 
result = subprocess.Popen("要运行的shell命令",shell=True,stdout=subprocess.PIPE,
         stderr=subprocess.PIPE)

    #read date from pipe
    stdoutMsg = ""
    stderrMsg = ""
    readbuf_msg  =  ""
    readbuf_errmsg =  ""
    buf_size = 1024
    select_rfds = [
result   .stdout, result   .stderr]
    while len(select_rfds) >0:
        (rfds,wfds,efds) = select.select(select_rfds,[],[])
        if 
  result .stdout in rfds:
           
  readbuf_msg   =   result   .stdout.read( buf_size           
            if len(
readbuf_msg ) == 0:
                select_rfds.remove(
result .stdout)
            else:
                stdoutMsg = stdoutMsg +
  readbuf_msg
               
        if
  result   .stderr in rfds:
           
  readbuf_errmsg   =   result   .stderr.read( buf_size )
                   
            if len(
readbuf_errmsg ) == 0:
                select_rfds.remove(
result .stderr)
            else:
                stderrMsg = stderrMsg + rest_err

   
  result .wait()  //等待字进程结束(等待shell命令结束) 
    exit_code =
  result .returncode
    ##(stdoutMsg,stderrMsg) =
  result   .communicate()#非阻塞时读法.
    str_ret = stdoutMsg + stderrMsg
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值