day24 三阶段总结
课程目标:对第三模块 阶段的知识点进行总结和考试,更好的掌握此模块的相关知识。
课程概要:
- 知识补充
- 阶段总结(思维导图)
- 考试题
1. 知识点补充
1.1 并发编程 & 网络编程
从知识点的角度来看,本身两者其实没有什么关系:
-
网络编程,基于网络基础知识、socket模块实现网络的数据传输。
-
并发编程,基于多进程、多线程等 来提升程序的执行效率。
但是,在很多 “框架” 的内部其实会让两者结合起来,使用多进程、多线程等手段来提高网络编程的处理效率。
案例1:多线程socket服务端
基于多线程实现socket服务端,实现同时处理多个客户端的请求。
-
服务端
import socket import threading def task(conn): while True: client_data = conn.recv(1024) data = client_data.decode('utf-8') print("收到客户端发来的消息:", data) if data.upper() == "Q": break conn.sendall("收到收到".encode('utf-8')) conn.close() def run(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('127.0.0.1', 8001)) sock.listen(5) while True: # 等待客户端来连接(主线程) conn, addr = sock.accept() # 创建子线程 t = threading.Thread(target=task, args=(conn,)) t.start() sock.close() if __name__ == '__main__': run()
-
客户端
import socket # 1. 向指定IP发送连接请求 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 8001)) while True: txt = input(">>>") client.sendall(txt.encode('utf-8')) if txt.upper() == 'Q': break reply = client.recv(1024) print(reply.decode("utf-8")) # 关闭连接,关闭连接时会向服务端发送空数据。 client.close()
案例2:多进程socket服务端
基于多进程实现socket服务端,实现同时处理多个客户端的请求。
-
服务端
import socket import multiprocessing def task(conn): while True: client_data = conn.recv(1024) data = client_data.decode('utf-8') print("收到客户端发来的消息:", data) if data.upper() == "Q": break conn.sendall("收到收到".encode('utf-8')) conn.close() def run(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('127.0.0.1', 8001)) sock.listen(5) while True: # 等待客户端来连接 conn, addr = sock.accept() # 创建了子进程(至少有个线程) t = multiprocessing.Process(target=task, args=(conn,)) t.start() sock.close() if __name__ == '__main__': run()
-
客户端
import socket # 1. 向指定IP发送连接请求 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 8001)) while True: txt = input(">>>") client.sendall(txt.encode('utf-8')) if txt.upper() == 'Q': break reply = client.recv(1024) print(reply.decode("utf-8")) # 关闭连接,关闭连接时会向服务端发送空数据。 client.close()
1.2 并发和并行
如何来理解这些概念呢?
-
串行,多个任务排队按照先后顺序逐一去执行。
-
并发,假设有多个任务,只有一个CPU,那么在同一时刻只能处理一个任务,为了避免串行,可以让任务切换运行(每个任务运行一点,然后再切换),达到并发效果(看似都在同时运行)。
并发在Python代码中体现:协程、多线程(由于CPython的GIL锁限制,多个线程无法被CPU调度)。
-
并行,假设有多个任务,有多个CPU,那么同一时刻每个CPU都是执行一个任务,任务就可以真正的同时运行。
并行在Python代码中的体现:多进程。
1.3 单例模式
在python开发和源码中关于单例模式有两种最常见的编写方式,分别是:
-
基于
__new__
方法实现import threading import time class Singleton: instance = None lock = threading.RLock() def __init__(self): self.name = "白居易" def __new__(cls, *args, **kwargs): if cls.instance: return cls.instance with cls.lock: if cls.instance: return cls.instance # time.sleep(0.1) cls.instance = object.__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() print(obj1 is obj2) # True
-
基于模块导入方式
# utils.py class Singleton: def __init__(self): self.name = "白居易" ... single = Singleton()
from xx import single print(single) from xx import single print(single)