Python 10th Day
列表推导式 (list comprehension)
格式:[thing for thing in list_of_things]
for 左边是会添加到列表中的内容,比如:
def list_doubler(lst): return [num * 2 for num in lst]
等于
def list_doubler(lst): doubled = [] for num in lst: doubled.append(num*2) return doubled
所以,下面这个例子中的返回值是一个由 lambda 函数组成的列表,但是函数并没有被执行。
li = [lambda :x for x in range(10)]
当执行列表中的一个函数时,因为 for 循环最后 x 最后被赋值为 9, 所以执行 lambda 函数返回 9
ret = li[0]()
IO 多路复用 (I/O multiplexing)
select: Low-level I/O multiplexing module. It monitors sockets, open files, and pipes (anything with a fileno() method that returns a valid file descriptor) until they become readable or writable, or a communication error occurs. select() makes it easier to monitor multiple connections at the same time, and is more efficient than writing a polling loop in Python using socket timeouts, because the monitoring happens in the operating system network layer, instead of the interpreter.
Classes hierarchy:
BaseSelector +-- SelectSelector +-- PollSelector +-- EpollSelector +-- DevpollSelector +-- KqueueSelector
BaseSelector:
- A BaseSelector is used to wait for I/O event readiness on multiple file objects
- It’s an abstract base class, so cannot be instantiated
下面我们主要介绍 select.select 方法,这个方法可以直接调用 POSIX (both of Unix and Windows) function select(), three lists containing communication channels to monitor:
select.select(rlist, wlist, xlist[, timeout]),
- rlist: a list of the objects to be checked for incoming data to be read
- wlist: contains objects that will receive outgoing data when there is room in their buffer
- xlist: wait for an “exceptional condition”
简单来说 rlist, wlist, xlist 分别用来监听 read events, write events 以及 error events.
示例程序:
#!/usr/bin/env python import socket import select # create server side socket obj that serving for new connection sk_obj = socket.socket() sk_obj.bind(('127.0.0.1', 3000,)) sk_obj.listen(5) inputs = [sk_obj,] outputs = [] message = {} while True: # rlist has elem when accept new connection ''' select() returns three new lists, containing subsets of the contents of the lists passed in All of the sockets in the [rlist] list have incoming data buffered and available to be read All of the sockets in the [wlist] list have free space in their buffer and can be written to The sockets returned in [elist] have had an error ''' rlist,wlist,elist, = select.select(inputs, outputs, inputs, 1) # print(len(inputs), len(rlist), len(outputs), len(wlist)) ''' 监听 sk_obj 对象, 如果有新连接, select.select 函数返回的 rlist 为 [sk_obj,] 监听 conn 对象, 如果 conn 变化, 表示客户端发送新消息, 此时 rlist 的值为发送消息的客户端 rlist 中可能有 sk_obj 或者 conn 如果是 sk_obj 说明有新连接, 那么把为这个新连接创建的 conn 添加进 rlist 如果是 conn 说明客户端有发送数据, 那么把 conn 添加进 wlist ''' # iterate the readable sockets for r in rlist: ''' If the socket is the main “server” socket (sk_obj), the one being used to listen for connections, then the “readable” condition means it is ready to accept another incoming connection ''' if r is sk_obj: conn, addr = r.accept() ''' adding the new connection to the list of inputs to monitor this section sets the client socket to not block: conn.setblocking(0) ''' inputs.append(conn) message[conn] = [] conn.sendall("hello".encode(encoding='utf-8')) # for established connection with a client has sent data else: try: # conn.recv data = r.recv(1024) # A readable client socket has data if data: # Add output channel for response outputs.append(r) message[r].append(data) # A readable socket without data available is from a client that has disconnected, # and the stream is ready to be closed else: inputs.remove(r) r.close() del message[r] # raise Exception('close connection') # Stop listening for input on the connection except Exception as e: inputs.remove(r) r.close() del message[r] for w in wlist: msg = message[w].pop() response = msg + 'response'.encode(encoding='utf-8') w.sendall(response) outputs.remove(w) for e in elist: inputs.remove(r) r.close() del message[r]

浙公网安备 33010602011771号