select模块
select模块
1. select模块
源:select.py
This module provides access to the select() and poll() functions available in most operating systems, devpoll() available on Solaris and derivatives, epoll() available on Linux 2.5+ and kqueue() available on most BSD.
该模块中select() and poll()方法在大多数操作系统中可用,devpoll()在Solaris and derivatives中可用,epoll()在Linux2.5+中可用,kqueue()在大多数bsd中可用。
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 used on regular files to determine whether a file has grown since it was last read.
注意:在win系列中,它只对sockets有用;在其它平台,file types也可使用(看起来类似pipes),它不能用于确定一个文件的大小是否增长。
1.1. 定义对象
模块定义了以下对象:
1.1.1. exception select.error
A deprecated alias of OSError.
Changed in version 3.3: Following PEP 3151, this class was made an alias of OSError.
异常类,略。
1.1.2. select.devpoll()
(Only supported on Solaris and derivatives.) Returns a /dev/poll polling object;
略
1.1.3. select.epoll(sizehint=-1, flags=0)
(Only supported on Linux 2.5.44 and newer.) Return an edge polling object, which can be used as Edge or Level Triggered interface for I/O events.
sizehint informs epoll about the expected number of events to be registered. It must be positive, or -1 to use the default. It is only used on older systems where epoll_create1() is not available; otherwise it has no effect (though its value is still checked).
flags is deprecated and completely ignored. However, when supplied, its value must be 0 or select.EPOLL_CLOEXEC, otherwise OSError is raised.
See the Edge and Level Trigger Polling (epoll) Objects section below for the methods supported by epolling objects.
epoll objects support the context management protocol: when used in a with statement, the new file descriptor is automatically closed at the end of the block.
The new file descriptor is non-inheritable.
Changed in version 3.3: Added the flags parameter.
Changed in version 3.4: Support for the with statement was added. The new file descriptor is now non-inheritable.
Deprecated since version 3.4: The flags parameter. select.EPOLL_CLOEXEC is used by default now. Use os.set_inheritable() to make the file descriptor inheritable.
1.1.4. select.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 Polling Objects below for the methods supported by polling objects.
1.1.5. select.kqueue()
(Only supported on BSD.) Returns a kernel queue object; see section Kqueue Objects below for the methods supported by kqueue objects.
The new file descriptor is non-inheritable.
Changed in version 3.4: The new file descriptor is now non-inheritable.
1.1.6. select.kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)
(Only supported on BSD.) Returns a kernel event object; see section Kevent Objects below for the methods supported by kevent objects.
1.1.7. select.select(rlist, wlist, xlist[, timeout])
This is a straightforward interface to the Unix select() system call.
它是一个直达式接口,指向unix select()系统调用。
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:
前三个参数是“可等待对象”序列,要么是整数-用于描述文件描述符;要么是一个名为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) 等待一个异常条件
Empty sequences are allowed, but acceptance of three empty sequences is platform-dependent. (It is known to work on Unix but not on Windows.)
空序列是可以的,但具体情况依赖于平台。unix支持,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.
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.
可选参数time-out指定一个浮点数,单位秒。
当它未指定时,函数阻塞直至至少一个fd就绪。
它为0意为查询一次,且不阻塞,立即返回。
返回值是三个就绪对象列表组合,它是三个参数的子集。
当超时点到达,且无一个fd就绪,返回三个空列表。
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 underlyingselect() function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.
注意事项:对于本函数而言,windows fd是不可接受对象,但sokets可以。
在windows中,select()底层实现由WinSock library提供,不能处理非源自Winsock的fd。
1.1.8. select.PIPE_BUF
The minimum number of bytes which can be written without blocking to a pipe when the pipe has been reported as ready for writing by select(), poll() or another interface in this module. This doesn’t apply to other kind of file-like objects such as sockets.
This value is guaranteed by POSIX to be at least 512.
Availability: Unix
2. 案例
2.1. select()
总结:
实测中发现socket一直是可读状态。
1.select会被调用很多次, 这就意味着:
当文件描述符过多时,文件描述符在用户空间与内核空间进行copy会很费时
当文件描述符过多时,内核对文件描述符的遍历也很浪费时间
select最大仅仅支持1024个文件描述符
#coding:utf-8
"""
----------------------------------------
description:
author: sss
date:
----------------------------------------
change:
----------------------------------------
"""
__author__ = 'sss'
def pr_type(i, info=''):
print(info, i,
type(i))
import select
import socket
import queue
from time import sleep
# 并发服务端
def server_select():
# create socket
server =
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 非阻塞模式
server.setblocking(False)
# bind the socket to
the port
server_addr = ('localhost', 9009)
print('server
running, port {}'.format(server_addr))
server.bind(server_addr)
# listen for incoming
connections
server.listen(5)
# define rlist
inputs = [server]
outputs = [] # wlist
message_queues = {}
while inputs:
print('waiting
for the next event.')
readable, writable, exceptional =
select.select(inputs, outputs, inputs)
#pr_type(readable)
#pr_type(writable)
#pr_type(exceptional)
for s in readable:
if s is server:
connection,
client_address = s.accept()
print('connection
from {}'.format(client_address))
connection.setblocking(0)
inputs.append(connection)
message_queues[connection] = queue.Queue()
else:
data = s.recv(1024)
if data != '':
print('recived
"{}" from "{}"'.format(data,
s.getpeername()))
message_queues[s].put(data)
if s not in outputs:
outputs.append(s)
else:
print('closing',
client_address)
if s in outputs:
outputs.remove(s)
inputs.reverse(s)
s.close()
del message_queues[s]
for s in writable:
try:
message_queue = message_queues.get(s)
send_data = ''
if message_queue
is not None:
send_data =
message_queue.get_nowait()
else:
print('has
closed')
except queue.Empty:
print('{}'.format(s.getpeername()))
outputs.remove(s)
else:
if message_queue
is not None:
s.send(send_data)
else:
print('has
closed')
for s in exceptional:
print('exception
condition on', s.getpeername())
inputs.reverse(s)
if s in outputs:
outputs.remove(s)
s.close()
del message_queues[s]
sleep(1)
if __name__ == '__main__':
#pr_type('s')
server_select()
#coding:utf-8
"""
----------------------------------------
description:
author: sss
date:
----------------------------------------
change:
----------------------------------------
"""
__author__ = 'sss'
def pr_type(i, info=''):
print(info, i,
type(i))
import select
import socket
import queue
def client_select():
messages = ['This is
the message ', 'It will be sent ', 'in parts ', ]
server_address = ('localhost', 9009)
# create a TCP/IP
socket
socks =
[socket.socket(socket.AF_INET, socket.SOCK_STREAM)
, socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
, socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
]
print('connecting
to {} on port {}'.format(*server_address))
for s in socks:
s.connect(server_address)
for index,
message in enumerate(messages):
for s in socks:
print('{}:
sending "{}"'.format(s.getsockname(), message + str(index)))
s.send((message + str(index)).encode('utf-8'))
for s in socks:
data = s.recv(1024)
print ('%s:
received "%s"' % (s.getsockname(), data))
if data != "":
print ('closingsocket',
s.getsockname())
s.close()
if __name__ == '__main__':
#pr_type('s')
client_select()
2.2.
案例2
select()实现非阻塞IO
# !/usr/bin/env python
# *-* coding:utf-8 *-*
import socket
import select
import sys
import signal
class ChatServer():
def __init__(self, host,
port, timeout=10, backlog=5):
# 记录连接的客户端数量
self.clients
= 0
# 存储连接的客户端socket和地址对应的字典
self.clientmap
= {}
# 存储连接的客户端socket
self.outputs
= []
# 建立socket
self.server =
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
self.server.bind((host,
port))
self.server.listen(backlog)
# 增加信号处理
signal.signal(signal.SIGINT,
self.sighandler)
def sighandler(self):
sys.stdout.write("Shutdown
Server......\n")
# 向已经连接客户端发送关系信息,并主动关闭socket
for output in self.outputs:
output.send("Shutdown
Server")
output.close()
# 关闭listen
self.server.close()
sys.stdout.flush()
# 主函数,用来启动服务器
def run(self):
# 需要监听的可读对象
inputs =
[self.server]
runing = True
# 添加监听主循环
while runing:
try:
readable, writeable,
exceptional = select.select(inputs, self.outputs, [])
# 此处会被select模块阻塞,只有当监听的三个参数发生变化时,select才会返回
except select.error
as e:
break
# 当返回的readable中含有本地socket的信息时,表示有客户端正在请求连接
if self.server in readable:
# 接受客户端连接请求
client,
addr = self.server.accept()
sys.stdout.write("New
Connection from %s\n" % str(addr))
sys.stdout.flush()
# 更新服务器上客户端连接情况
# 1,数量加1
# 2,self.outputs增加一列
# 3,self.clientmap增加一对
# 4, 给input添加可读监控
self.clients
+= 1
self.outputs.append(client)
self.clientmap[client]
= addr
inputs.append(client)
# readable中含有已经添加的客户端socket,并且可读
# 说明
1,客户端有数据发送过来或者 2,客户端请求关闭
elif len(readable)
!= 0:
# 1, 取出这个列表中的socket
csock = readable[0]
# 2, 根据这个socket,在事先存放的clientmap中,去除客户端的地址,端口的详细信息
host, port = self.clientmap[csock]
# 3,取数据,
或接受关闭请求,并处理
# 注意,这个操作是阻塞的,但是由于数据是在本地缓存之后,所以速度会非常快
try:
data = csock.recv(1024).strip()
for cs in self.outputs:
if cs !=
csock:
cs.send("%s\n" % data)
except socket.error
as e:
self.clients -=
1
inputs.remove(csock)
self.outputs.remove(csock)
del self.clientmap[csock]
# print self.outputs
self.server.close()
if __name__ == "__main__":
chat = ChatServer("", 8008)
chat.run()
运行这个脚本,然后用任意客户端如telnet或netcat连接8008端口,多个客户端之间就可以进行对话。
其实select模块本身是阻塞的,当需要监控的socket发生变化时,select作出返回,下面的程序会继续执行,程序根据select的返回值,对各种情况作出处理。
select模块的更多相关文章
- 第五十五节,IO多路复用select模块加socket模块,伪多线并发
IO多路复用select模块加socket模块,伪多线并发,并不是真正的多线程并发,实际通过循环等待还是一个一个处理的 IO多路复用,lo就是文件或数据的输入输出,IO多路复用就是可以多用户操作 IO ...
- python中的select模块
介绍: Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqu ...
- python select模块详解
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...
- python select.select模块通信全过程详解
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...
- Selenium:利用select模块处理下拉框
在利用selenium进行UI自动化测试过程中,经常会遇到下拉框选项,这篇博客,就介绍下如何利用selenium的Select模块来对标准select下拉框进行操作... 首先导入Select模块: ...
- Python自动化开发 - select模块
介绍: IO-多路复用:监听多个socker对象是否有变化,包括可读.可写.发送错误 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个 ...
- 深入理解python中的select模块
简介 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kque ...
- python下的select模块使用 以及epoll与select、poll的区别
python下的select模块使用 以及epoll与select.poll的区别 先说epoll与select.poll的区别(总结) 整理http://www.zhihu.com/question ...
- Python之基于socket和select模块实现IO多路复用
'''IO指的是输入输出,一部分指的是文件操作,还有一部分网络传输操作,例如soekct就是其中之一:多路复用指的是利用一种机制,同时使用多个IO,例如同时监听多个文件句柄(socket对象一旦传送或 ...
- python学习之-- IO多路复用 select模块
python I/O多路复用包括3个模块,上一篇已经说过概念,这里我使用的是select模块实现一个ftp并发 服务器端核心代码: import socket,select import queue, ...
随机推荐
- ASA映射80端口到公网
1.测试拓扑: 2.测试目的:Web Server:192.168.1.100/24 GW:192.168.1.254Internet:200.1.1.2/24 映射的地址:200.1.1.3 3.配 ...
- 有趣、实用的c# 游戏源码下载网站
在游戏开发的学习或工作中,利用完好的游戏源码可以事半功倍,不仅可以逆向学习开拓思维,也可以大大减少设计周期. 那想用c#来编写游戏的话,游戏源码在哪里找呢?下面整理了几个性价比高一些的网站,推荐给大家 ...
- 510,position的值,relative和absolute定位原点是
(absolute:生成绝对定位的元素) position属性用来规定元素的定位类型和方式 ①position:static 默认值,没有定位,元素出现在正常的流中: ②position:fixed ...
- python连接oracle数据库报错"DatabaseError: DPI-1047: 64-bit Oracle Client library cannot be loaded: "解决方案
操作系统,python3.5, oracle_11, 均为64位:plsql 正常连接. 也顺利安装了cx_oracle 6.3,但是python进行连接的时候就会报错"DatabaseEr ...
- CentOS6.5_x64安装MySQL-5.6.17,在已经启动MySQL服务的情况下,出现密码报错ERROR 2002 (HY000)
1.修改MySQL配置文件,使MySQL登陆时跳过密码验证 skip-grant-tables 2.重启MySQL服务 service mysql restart 3.进入MySQL,修改user表中 ...
- eclipse好用的快捷键
eclipse一些增加工作效率的快捷键(部分自己添加) eclipse如何修改快捷键 1. shift + enter | ctrl + shift + enter 在下/上方增加空行 2. ctrl ...
- 在 Fabric 中使用私有数据
本教程将演示收集器(collection)的使用,收集器为区块链网络上已授权的组织节点 提供私有数据的存储和检索. 本教程假设您已了解私有数据的存储和他们的用例.更多的信息请参阅 私有数据 . 本教程 ...
- STM32 MDK C 常见易错点
1.MDK编译器单字节的负数-1,-2,-3... ... 处理:存储,类型转换,位对齐. char 定义的变量在运算过程尤其类型转换,逻辑比大少会被当做 unsigned char 处理,这里很容易 ...
- 安装RabbitMQ,一直提示Erlang版本过低
1.背景 windows系统,控制面板卸载Erlang后,重新安装Erlang成功,当再安装RabbitMQ时,报如下提示: 意思就是说Erlang版本过低,请安装更高的版本. 出现上面问题的原因,是 ...
- markdown列表
Markdown 列表 Markdown 支持有序列表和无序列表. 无序列表使用星号(*).加号(+)或是减号(-)作为列表标记: * 第一项 * 第二项 * 第三项 + 第一项 + 第二项 + 第三 ...