Python之路_Day10_课堂笔记
上节回顾:
socket:
1、导入模块2、创建socket
3、
字节send:每次发送可能没有完全发送,send发送后会有一个返回值,是本次发送了多少。sendall:循环发送,直到全部发送完全。接收recv(2048):最多可以接收2048字节,上传文件时需要注意
粘包:
socketserver:
1、自定义类
2、继承socketserver.BaseRequestHandler类
3、重写handle方法
4、socketserver 调用上面的类
5、运行
本节内容:
一、作业问题:
1、socket发送字符串2、socket发送文件
客户端:
文件大小发消息
服务端:
接收消息(文件大小)
断点续传
文件打开方法:
a:追加w:清空写
文件指针:seek(num)
二、小知识
三、python27多继承,python35多继承
四、socketserver源码
支持并发处理socketsocket源码
五、IO多路复用
六、多线程、多进程
Alex甄嬛西游转
一、小知识
作用域
Python中无块级作用域Java/C# 不可以运行python/javascript 可以运行
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python中无块级作用域
if 1 == 1:
name = ‘sandler‘
print(name)
Python中以函数为作用域
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python中以函数为作用域
def func():
name = ‘alex‘
func()
print(name)
Python作用域链,由内向外找,直到找不到报错
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python作用域链,由内向外找,直到找不到报错
name = ‘sandler‘
def f1():
name = ‘f1‘
def f2():
name = ‘f2‘
print(name)
f1()
Python在函数为执行前,作用域已经确定,作用域链也已经确定
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# Python在函数为执行前,作用域已经确定,作用域链也已经确定
name = ‘sandler‘
def f1():
print(name)
def f2():
name = ‘yuli‘
f1()
f2()
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
li = [lambda :x for x in range(10)]
# li列表
# li列表中的元素:【函数,函数,函数...】
# 函数在没有执行前,内部代码不执行
# ?li[0],函数
# ?函数()
# 返回值是????
print(li[0]())
二、python27多继承,python35多继承
Python2
新式类
经典类==>一条道走到黑
Python3
三、SocketServer源码
支持并发处理socket
Socket源码
1、TCPServer =====> __init__()
2、BaseServer =====> __init__()
3、BaseServer =====> server_forever()
4、BaseServer =====> _handle_request_noblock()
5、ThreadingMixIn ===> process_request()
6、ThreadingMixIn ===> process_request_thread()
7、BaseServer =====> finish_process()
8、BaseServer =====>
9、MyClass
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# socketserver源码
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,listen
obj = socketserver.ThreadingTCPServer((‘127.0.0.1‘,9999),MyClass)
obj.serve_forever()
四、IO多路复用
概述:
select、poll、epoll
监听socket对象内部是否变化了?
什么时候变化?连接或收发消息
服务器端的socket对象发生变化==>有新链接来了....
sk:有新链接来了....
conn:有新消息了,要收“发”消息了
IO多路复用===>监听socket对象内部是否变化了?
IO多路复用测试
Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
import select
sk = socket.socket()
sk.bind((‘127.0.0.1‘,9999,))
sk.listen(5)
while True:
rlist, w, e, = select.select([sk,],[],[],1)
print(rlist)
for r in rlist:
print(r)
conn, address = r.accept()
conn.sendall(bytes(‘hello‘,encoding=‘utf-8‘))
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
sk = socket.socket()
sk.connect((‘127.0.0.1‘, 9999,))
data = sk.recv(1024)
print(data)
while True:
input(‘>>> ‘)
sk.close()
IO多路复用测试(第二版)
Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
import select
sk = socket.socket()
sk.bind((‘127.0.0.1‘,9999,))
sk.listen(5)
inputs = [sk,]
while True:
rlist, w, e, = select.select(inputs,[],[],1)
print(len(inputs),len(rlist))
# 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
for r in rlist:
if r == sk:
conn, address = r.accept()
# conn是什么?conn其实是socket对象
inputs.append(conn)
conn.sendall(bytes(‘hello‘,encoding=‘utf-8‘))
else:
r.recv(1024)
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
import socket
sk = socket.socket()
sk.connect((‘127.0.0.1‘, 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input(‘>>> ‘)
sk.sendall(bytes(inp,encoding=‘utf-8‘))
sk.close()
IO多路复用测试之读写分离
Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试服务端
import socket
import select
sk = socket.socket()
sk.bind((‘127.0.0.1‘,9999,))
sk.listen(5)
inputs = [sk,]
outputs = []
while True:
rlist, wlist, e, = select.select(inputs,outputs,[],1)
print(len(inputs),len(rlist),len(outputs),len(wlist))
# 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
for r in rlist:
if r == sk:
conn, address = r.accept()
# conn是什么?conn其实是socket对象
inputs.append(conn)
conn.sendall(bytes(‘hello‘,encoding=‘utf-8‘))
else:
print(‘========‘)
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
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试客户端
import socket
sk = socket.socket()
sk.connect((‘127.0.0.1‘, 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input(‘>>> ‘)
sk.sendall(bytes(inp,encoding=‘utf-8‘))
print(sk.recv(1024))
sk.close()
IO多路复用测试之读写分离(升级版)
Server
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试服务端
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, e, = select.select(inputs,outputs,[],1)
print(len(inputs),len(rlist),len(outputs),len(wlist))
# 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
for r in rlist:
if r == sk:
conn, address = r.accept()
# conn是什么?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].appent(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)
Client
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 读写分离测试客户端
import socket
sk = socket.socket()
sk.connect((‘127.0.0.1‘, 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input(‘>>> ‘)
sk.sendall(bytes(inp,encoding=‘utf-8‘))
print(sk.recv(1024))
sk.close()
五、多线程、多进程
1、一个应用程序,可以有多进程和多线程
2、默认:单进程,单线程
3、单进程,多线程
IO操作,不占用CPU
多线程提高并发
计算型操作,占用CPU
多进程提供并发
4、GIL,全局解释器锁
==================================>>
多线程、多进程 提供并发
IO密集型:使用多线程
计算密集型:使用多进程
多线程示例:
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 多线程并发
import threading
import time
def f1(args):
time.sleep(1)
print(args)
t = threading.Thread(target=f1, args=(123,))
t.start()
f1(111)
多线程示例2:
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 多线程并发
import threading
import time
def f1(args):
time.sleep(5)
print(args)
# 单进程,单线程的应用程序
for i in range(10):
f1(i)
# 单进程,多线程的应用程序
for i in range(10):
t = threading.Thread(target=f1, args=(i,))
t.setDaemon(True) # true,表示主线程不等此子线程结束,
t.start() # 不代表当前线程会被立即执行
t.join() # 表示主线程到此,等待子线程执行结束,才会继续往下执行,参数表示主线程在此最多等待几秒