1. 作用域
1.1 作用域
代码1
if 1 == 1:
name = 'alex'
for i in range(10):
name = i
print(name)
# Java/C# 不可以
# Python/JavaScript 可以
# Python中无块级作用域
代码2:函数
def func():
name = 'alex'
print(name)
def func():
name = 'alex'
func()
print(name)
# Python中以函数为作用域
代码3:
name = 'alex'
def f1():
print(name)
def f2():
name='eric'
f1()
f2()
# Python的作用域在执行之前已经确
代码4:
name = 'alex'
def f1():
print(name)
def f2():
name = 'eric'
return f1
ret = f2()
ret()
# Python作用域链,由内向外找,直到找不到报错
代码5:
li = [x+100 for x in range(10) if x>6]
print(li)
代码6:
li = [lambda :x for x in range(10)]
r = li[0]()
print(r)
# 剖析
# li类型:列表
# li列表中的元素:[函数, 函数, 函数...]
# 函数在没有执行前,内部代码不执行
# li[0],lambda函数
# 函数(),执行函数
# 返回值:9
代码7:
li = []
for i in range(10):
def f1():
return i
li.append(f1)
print(li[0]())
print(li[1]())
print(li[2]())
# 输出结果
# 9
# 9
# 9
li = []
for i in range(10):
def f1(x=i):
return x
li.append(f1)
print(li[0]())
print(li[1]())
print(li[2]())
# 输出结果
# 0
# 1
# 2
PS:本质上看代码是否执行
1.2 小结
- Python中无块级作用域
- Python中以函数为作用域
- Python作用域链,由内向外找,直到找不到报错
- Python的作用域在执行之前已经确定
1.3 Python多继承2.7版本与3.5版本
- Python 3所有的类都默认继承object,称新事类
- Python 2所有的类默认不继承object,称经典类
2. SocketServer及IO多路复用
2.1 socketserver基本执行过程
import socketserver
class MyClass(socketserver.BaseRequestHandler):
def handle(self):
pass
obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyClass)
obj.serve_forever()
# 创建socket对象
# accept 处理请求
# server_address = ('127.0.0.1', 9999)
# RequestHandlerClass = MyClass == ()
# self.RequestHandlerClass() = MyClass() == ()
# 1.obj封装了self.RequestHandlerClass = MyClass
# 2.创建了socket, bind, lister
2.2 通过IO多路复用实多并发
概述:
IO多路复用不占用CPU
select,poll,epoll (支持所有IO操作,不支持文件操作)
监听socket对象内部是否变化了?
什么时候变化?连接或收发消息
服务器端的socket发生变化,表示有新连接来了
sk: 有新连接来了
conn: 要收发消息了
IO多路复:监听socket对象内部是否变化了
1) 多并发连接实现
server
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1', 999, ))
sk.listen(5)
while True:
rlist,w,e, = select.select([sk,], [], [], 1) #1为超时时间
print(rlist)
# rlist中socket对象列表,[sk, ]
# 有新连接 rlist = [sk]
# 无连接 rlist = []
for r in rlist:
print(r)
conn, address = r.accept()
conn.sendall(bytes('hello', encoding='utf-8'))
client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 999, ))
data = sk.recv(1024)
print(data)
while True:
input(">>>")
sk.close()
2) IO多路复用实现伪并发,可收发消息
Server
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1', 999, ))
sk.listen(5)
inputs = [sk,]
while True:
rlist,w,e, = select.select(inputs, [], [], 1) #1为超时时间
print(len(inputs), len(rlist))
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,些时rlist值为[sk]
# 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,些时rlist的值为[客户端]
# rlist中socket对象列表,[sk, ]
# 有新连接 rlist = [sk]
# 无连接 rlist = []
for r in rlist:
if r == sk:
# 新客户来连接
conn, address = r.accept()
# conn是什么?其实也是socket对象
inputs.append(conn)
conn.sendall(bytes('hello', encoding='utf-8'))
else:
# 有人给我发消息了
r.recv(1024)
Client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 999, ))
data = sk.recv(1024)
print(data)
while True:
inp = input(">>>")
sk.sendall(bytes(inp, encoding='utf-8'))
sk.close()
3) 读写分离实现
Server
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1', 9998, ))
sk.listen(5)
inputs = [sk,]
outputs = []
while True:
rlist,wlist,e, = select.select(inputs, outputs, [], 1) #1为超时时间
print(len(inputs), len(rlist), len(wlist), len(outputs))
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,些时rlist值为[sk]
# 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,些时rlist的值为[客户端]
# rlist中socket对象列表,[sk, ]
# 有新连接 rlist = [sk]
# 无连接 rlist = []
for r in rlist:
if r == sk:
# 新客户来连接
conn, address = r.accept()
# conn是什么?其实也是socket对象
inputs.append(conn)
conn.sendall(bytes('hello', encoding='utf-8'))
else:
# 有人给我发消息了
try:
ret = r.recv(1024)
if not ret:
raise Exception('断开连接')
else:
outputs.append(r)
except Exception as e:
inputs.remove(r)
# 所有给我发过消息的人
for w in wlist:
w.sendall(bytes('response', encoding='utf-8')) #回复消息
outputs.remove(w) # 删除已回复消息的人
Client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9998, ))
data = sk.recv(1024)
print(data)
while True:
inp = input(">>>")
sk.sendall(bytes(inp, encoding='utf-8'))
print(sk.recv(1024))
sk.close()
4) 回复收到的消息
Server
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1', 9998, ))
sk.listen(5)
inputs = [sk,]
outputs = []
messages = {}
# del messages[alex] #删除alex的消息
# message = {
# alex:[msg1, msg2, ]
# eric:[msg1, msg2, ]
# }
while True:
rlist,wlist,e, = select.select(inputs, outputs, [], 1) #1为超时时间
print(len(inputs), len(rlist), len(wlist), len(outputs))
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,些时rlist值为[sk]
# 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,些时rlist的值为[客户端]
# rlist中socket对象列表,[sk, ]
# 有新连接 rlist = [sk]
# 无连接 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:
# 有人给我发消息了
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) # 删除已回复消息的wlist
Client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9998, ))
data = sk.recv(1024)
print(data)
while True:
inp = input(">>>")
sk.sendall(bytes(inp, encoding='utf-8'))
print(sk.recv(1024))
sk.close()
ThredingTCPServer源码剖析
PS:所有查找都要遵循一切从原点开始
第3章 进程与线程
3.1 多线程多进程
概述:
1、一个应用程序,可以有多进程和多线程
2、默认:单进程,单线程
3、单进程,多线程
l IO操作,不占用CPU
多线程提高并发
l 计算性操作,占用CPU
多进程提高并发
4、GIL,全局解释器锁
小结:
- 多线程多进程的目的提供并发
- IO密集型:多线程
- 计算密集型:多进程
PS:IO操作,不占用CPU GIL,全局解释器锁
3.2 如何建立多线程
练习创建主线程,子线程
import threading
t = threading.Thread(target=f1, args=(123,))
t.start() #不代表当前纯种会被立即执行
f1(111) #主线程
基本配置参数
import threading
t = threading.Thread(target=f1, args=(123,))
t.setDaemon(True) # true,表示主线程不等此子线程
t.start() # 不代表当前纯种会被立即执行
t.join(5) # 表示主线程至此,等待....,直到子线程执行完毕
# 参数:表示主线程最多等待时间n秒
# f1(111) #主线程
print('end')
print('end')
print('end')
print('end')
import socketserver
class MyClass(socketserver.BaseRequestHandler):
def handle(self):
pass
# 创建socket对象
# accept 处理请求
# server_address = ('127.0.0.1', 9999)
# RequestHandlerClass = MyClass == ()
# self.RequestHandlerClass() = MyClass() == ()
# 1.obj封装了self.RequestHandlerClass = MyClass
# 2.创建了socket, bind, lister
obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyClass)
obj.serve_forever()