day24 三阶段总结
课程目标:对第三模块 阶段的知识点进行总结和考试,更好的掌握此模块的相关知识。
课程概要:
1. 知识点补充
1.1 并发编程 & 网络编程
从知识点的角度来看,本身两者其实没有什么关系:
但是,在很多 “框架” 的内部其实会让两者结合起来,使用多进程、多线程等手段来提高网络编程的处理效率。
案例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)