Python之路_Day10

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源码
支持并发处理socket
socket源码

五、IO多路复用

六、多线程、多进程
Alex甄嬛西游转


一、小知识
作用域
Python中无块级作用域
Java/C#                  不可以运行
python/javascript    可以运行
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # Python中无块级作用域
  5. if 1 == 1:
  6. name = 'sandler'
  7. print(name)

Python中以函数为作用域
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # Python中以函数为作用域
  5. def func():
  6. name = 'alex'
  7. func()
  8. print(name)

Python作用域链,由内向外找,直到找不到报错
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # Python作用域链,由内向外找,直到找不到报错
  5. name = 'sandler'
  6. def f1():
  7. name = 'f1'
  8. def f2():
  9. name = 'f2'
  10. print(name)
  11. f1()

Python在函数为执行前,作用域已经确定,作用域链也已经确定
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # Python在函数为执行前,作用域已经确定,作用域链也已经确定
  5. name = 'sandler'
  6. def f1():
  7. print(name)
  8. def f2():
  9. name = 'yuli'
  10. f1()
  11. f2()


  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. li = [lambda :x for x in range(10)]
  5. # li列表
  6. # li列表中的元素:【函数,函数,函数...】
  7. # 函数在没有执行前,内部代码不执行
  8. # ?li[0],函数
  9. # ?函数()
  10. # 返回值是????
  11. print(li[0]())
36672W]@8C]YZGJ6$F]0T4U.png
5T(%VD]92ZVRQ4QWVH7A$GP.png



二、python27多继承,python35多继承
Python2
新式类
经典类==>一条道走到黑
Python3








三、SocketServer源码
支持并发处理socket

Socket源码
UT9OZOD`}YNZ%RQUX`}BVGQ.png
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

  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # socketserver源码
  5. import socketserver
  6. class MyClass(socketserver.BaseRequestHandler):
  7. def handle(self):
  8. pass
  9. # 创建socket对象
  10. # accept
  11. # server_address = ('127.0.0.1',9999)
  12. # RequestHandlerClass = MyClass == ()
  13. # self.RequestHandlerClass() = MyClass() == ()
  14. # 1、obj封装了self.RequestHandlerClass = MyClass
  15. # 2、创建了socket,bind,listen
  16. obj = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyClass)
  17. obj.serve_forever()






四、IO多路复用
概述:
select、poll、epoll
监听socket对象内部是否变化了?
什么时候变化?连接或收发消息
服务器端的socket对象发生变化==>有新链接来了....
sk:有新链接来了....
conn:有新消息了,要收“发”消息了
IO多路复用===>监听socket对象内部是否变化了?

IO多路复用测试
Server
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. import socket
  5. import select
  6. sk = socket.socket()
  7. sk.bind(('127.0.0.1',9999,))
  8. sk.listen(5)
  9. while True:
  10. rlist, w, e, = select.select([sk,],[],[],1)
  11. print(rlist)
  12. for r in rlist:
  13. print(r)
  14. conn, address = r.accept()
  15. conn.sendall(bytes('hello',encoding='utf-8'))

Client
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. import socket
  5. sk = socket.socket()
  6. sk.connect(('127.0.0.1', 9999,))
  7. data = sk.recv(1024)
  8. print(data)
  9. while True:
  10. input('>>> ')
  11. sk.close()

IO多路复用测试(第二版)
Server
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. import socket
  5. import select
  6. sk = socket.socket()
  7. sk.bind(('127.0.0.1',9999,))
  8. sk.listen(5)
  9. inputs = [sk,]
  10. while True:
  11. rlist, w, e, = select.select(inputs,[],[],1)
  12. print(len(inputs),len(rlist))
  13. # 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
  14. # 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
  15. for r in rlist:
  16. if r == sk:
  17. conn, address = r.accept()
  18. # conn是什么?conn其实是socket对象
  19. inputs.append(conn)
  20. conn.sendall(bytes('hello',encoding='utf-8'))
  21. else:
  22. r.recv(1024)

Client
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. import socket
  5. sk = socket.socket()
  6. sk.connect(('127.0.0.1', 9999,))
  7. data = sk.recv(1024)
  8. print(data)
  9. while True:
  10. inp = input('>>> ')
  11. sk.sendall(bytes(inp,encoding='utf-8'))
  12. sk.close()

FI~1TYYN[(CTEY1JU90){XV.png
YI_ZDU[4YV066P0PLT[DG_7.png

IO多路复用测试之读写分离
Server
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # 读写分离测试服务端
  5. import socket
  6. import select
  7. sk = socket.socket()
  8. sk.bind(('127.0.0.1',9999,))
  9. sk.listen(5)
  10. inputs = [sk,]
  11. outputs = []
  12. while True:
  13. rlist, wlist, e, = select.select(inputs,outputs,[],1)
  14. print(len(inputs),len(rlist),len(outputs),len(wlist))
  15. # 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
  16. # 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
  17. for r in rlist:
  18. if r == sk:
  19. conn, address = r.accept()
  20. # conn是什么?conn其实是socket对象
  21. inputs.append(conn)
  22. conn.sendall(bytes('hello',encoding='utf-8'))
  23. else:
  24. print('========')
  25. try:
  26. ret = r.recv(1024)
  27. if not ret:
  28. raise Exception('断开连接')
  29. else:
  30. outputs.append(r)
  31. except Exception as e:
  32. inputs.remove(r)
  33. for w in wlist:
  34. w.sendall(bytes('response',encoding='utf-8'))
  35. outputs.remove(w)

Client
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # 读写分离测试客户端
  5. import socket
  6. sk = socket.socket()
  7. sk.connect(('127.0.0.1', 9999,))
  8. data = sk.recv(1024)
  9. print(data)
  10. while True:
  11. inp = input('>>> ')
  12. sk.sendall(bytes(inp,encoding='utf-8'))
  13. print(sk.recv(1024))
  14. sk.close()

IO多路复用测试之读写分离(升级版)
Server
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # 读写分离测试服务端
  5. import socket
  6. import select
  7. sk = socket.socket()
  8. sk.bind(('127.0.0.1',9999,))
  9. sk.listen(5)
  10. inputs = [sk,]
  11. outputs = []
  12. messages = {}
  13. while True:
  14. rlist, wlist, e, = select.select(inputs,outputs,[],1)
  15. print(len(inputs),len(rlist),len(outputs),len(wlist))
  16. # 监听sk(服务器端)对象,如果sk对象发送变化,表示有客户端来连接了,此时rlist值为[sk]
  17. # 监听conn对象,如果conn发送变化,表示客户端有新消息发送过来,此时rlist的值为[客户端]
  18. for r in rlist:
  19. if r == sk:
  20. conn, address = r.accept()
  21. # conn是什么?conn其实是socket对象
  22. inputs.append(conn)
  23. messages[conn] = []
  24. conn.sendall(bytes('hello',encoding='utf-8'))
  25. else:
  26. print('========')
  27. try:
  28. ret = r.recv(1024)
  29. if not ret:
  30. raise Exception('断开连接')
  31. else:
  32. outputs.append(r)
  33. messages[r].appent(ret)
  34. except Exception as e:
  35. inputs.remove(r)
  36. del messages[r]
  37. for w in wlist:
  38. msg = messages[w].pop()
  39. resp = msg + bytes('response',encoding='utf-8')
  40. w.sendall(resp)
  41. outputs.remove(w)

Client
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # 读写分离测试客户端
  5. import socket
  6. sk = socket.socket()
  7. sk.connect(('127.0.0.1', 9999,))
  8. data = sk.recv(1024)
  9. print(data)
  10. while True:
  11. inp = input('>>> ')
  12. sk.sendall(bytes(inp,encoding='utf-8'))
  13. print(sk.recv(1024))
  14. sk.close()





五、多线程、多进程

1、一个应用程序,可以有多进程和多线程
2、默认:单进程,单线程
3、单进程,多线程
IO操作,不占用CPU
多线程提高并发
计算型操作,占用CPU
多进程提供并发

4、GIL,全局解释器锁
==================================>>
多线程、多进程 提供并发
IO密集型:使用多线程
计算密集型:使用多进程

多线程示例:
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # 多线程并发
  5. import threading
  6. import time
  7. def f1(args):
  8. time.sleep(1)
  9. print(args)
  10. t = threading.Thread(target=f1, args=(123,))
  11. t.start()
  12. f1(111)

多线程示例2:
  1. #!/usr/bin/env python
  2. # -.- coding: utf-8 -.-
  3. # By sandler
  4. # 多线程并发
  5. import threading
  6. import time
  7. def f1(args):
  8. time.sleep(5)
  9. print(args)
  10. # 单进程,单线程的应用程序
  11. for i in range(10):
  12. f1(i)
  13. # 单进程,多线程的应用程序
  14. for i in range(10):
  15. t = threading.Thread(target=f1, args=(i,))
  16. t.setDaemon(True) # true,表示主线程不等此子线程结束,
  17. t.start() # 不代表当前线程会被立即执行
  18. t.join() # 表示主线程到此,等待子线程执行结束,才会继续往下执行,参数表示主线程在此最多等待几秒




















































posted @ 2016-07-15 20:42  滚动的沙砾  阅读(214)  评论(0编辑  收藏  举报