Day10 IO多路复用,多线程,笔记
IO多路复用,多线程,笔记
一、笔记
笔记之lambda
li = [lambda:x for x in range(10)]
li 中的元素是什么?
li[0]()的结果是什么?
第一问:li 中的元素是10个相同功能的函数
第二问:li 循环第10次的时候x =9 ,所以li[0]()的结果是 9
笔记之Py27,Py35多继承
Python 27中:
经典类:
class A():
var = 'a'
def func(self):
print self.var
class B(A):
def f(self):
pass
class C(A):
var = 'c'
def func(self):
print self.var
class D(B,C):
def f(self):
pass
obj = D()
obj.func()
输出结果: a
寻找路径: D-->B-->A 经典类:深度优先遍历
新式类:
class A(object): # 注意新式类此处差异
var = 'a'
def func(self):
print self.var
class B(A):
def f(self):
pass
class C(A):
var = 'c'
def func(self):
print self.var
class D(B,C):
def f(self):
pass
obj = D()
obj.func()
输出结果: c
寻找路径: D-->B-->C--A 新式类:广度优先遍历
Py35 默认就是广度优先遍历方式
笔记之Python作用域
python中代码无块及作用域。Ptyon以函数为作用域
name = 'alex'
def f1():
print(name)
def f2():
name = 'eric'
f1()
f2()
输出结果:alex
为什么不是 eric?
python的作用域在执行之前已经确定!
Python作用域链,由内向外找,直到找不到报错!
name = 'alex'
def f1():
# name = 'a'
def f2():
# name = 'b'
print(name)
f2()
f1()
输出结果: alex
反注释 # name = 'b'
输出结果: b
反注释 # name = 'a'
输出结果: a
二、IO多路复用
与多线程和多进程相比,I/O多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程。
主要应用:
- 客户程序需要同时处理交互式的输入和服务器之间的网络连接
- 客户端需要对多个网络连接作出反应
- TCP服务器需要同时处理多个处于监听状态和多个连接状态的套接字
- 服务器需要处理多个网络协议的套接字
- 服务器需要同时处理不同的网络服务和协议
elect,poll,epoll都是IO多路复用的机制。所谓I/O多路复用机制,就是说通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。select能够监视的描述符有限制,最多1024,而poll可以突破该限制,epoll则是增强的机制,不再主动监视,而是被监视的描述符自己有变化主动回调。以select为例:
socket server:
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1', 9999,))
sk.listen(5)
inputs = [sk,]
outputs = []
messages = {}
while True:
rlist,wlist,elist, = select.select(inputs, outputs,[sk,],1)
print(len(inputs),len(rlist),len(wlist), len(outputs))
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为【sk】
# 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,此时rlist的之为 【客户端】
for r in rlist:
if r == sk:
# 新客户来连接
conn, address = r.accept()
# conn是什么?其实socket对象
inputs.append(conn)
messages[conn] = []
conn.sendall(bytes('hello', encoding='utf-8'))
else:
# 有人给我发消息了
print('=======')
try:
ret = r.recv(1024)
if not ret:
raise Exception('断开连接')
else:
outputs.append(r)
messages[r].append(ret)
except Exception as e:
inputs.remove(r)
del messages[r]
# 所有给我发过消息的人(读写分离)
for w in wlist:
msg = messages[w].pop()
resp = msg + bytes('response', encoding='utf-8')
w.sendall(resp)
outputs.remove(w)
socket client:
import socket
sk = socket.socket()
sk.connect(("127.0.0.1", 9999,))
recv_bytes = sk.recv(1024)
recv_str = str(recv_bytes, encoding='utf-8')
while True:
inp = input('>>>')
sk.sendall(bytes(inp, encoding='utf-8'))
if inp == 'q':
break
print(str(sk.recv(1024),encoding='utf-8'))
三、多线程,多进程
应用程序可以有多进程和多线程运行,一般写的程序都是单进程,但线程。由于Python存在GIL,即全局解释器锁,所以对于不占用CPU的IO密集型操作可以使用多线程来提高并发,而对于占用CPU的计算密集型操作可以使用多进程来提高并发。
多线程:
import threading
import time
def f1(args):
time.sleep(1)
print(args)
def f2(args):
time.sleep(3)
print(args)
print('alex')
t = threading.Thread(target=f2, args=('Wu', )) # target指定函数名,args传进的参数
t.setDaemon(True) # true,表示主线程不等此子线程
t.start() # 不代表当前线程会被立即执行
t.join(2) # 表示主线程到此,等待 ... 直到子线程执行完毕 参数n表示主线程在此最多等待n秒
f1('eric')