Python socketserver、进程、线程、协程
一、socketserver
import socketserver # socketserver所启动的服务端是不能有input操作的 # server端一般都是根据client端的要求去执行固定的代码 class MyServer(socketserver.BaseRequestHandler): def handle(self): conn = self.request while True: msg = conn.recv(1024).decode("utf-8") address = self.client_address if hasattr(self, msg): print("%s:%s" % (address, msg)) getattr(self, msg)() def ls(self): print("%s:in ls" % self.client_address[1]) def du(self): print("%s:in du" % self.client_address[1]) my_server = socketserver.ThreadingTCPServer(("127.0.0.1", 9000), MyServer) my_server.serve_forever()
#!/usr/bin/env python3 import socket client = socket.socket() client.connect(("127.0.0.1", 9000)) while True: msg = input(">>>:").encode("utf-8") if not msg:continue client.send(msg) if msg == "q": break client.close()
二、进程
# 什么是进程 :运行中的程序 # 进程是操作系统中资源分配的最小单位 # 进程与进程之间都是异步的 # 开启一个进程是有时间开销的 # 启动多个进程 from multiprocessing import Process import os import time import random def func(): time.sleep(random.randint(0,3)) print("run",os.getpid()) if __name__ == '__main__': for i in range(10): p = Process(target=func) p.start() # 程序开始执行就会产生一个主进程 # python中可以主进程中用代码启动一个进程 —— 子进程 # 同时主进程也被称为父进程 # 父子进程之间的代码执行是异步的,各自执行自己的 # 父子进程之间的数据不可以共享 # 主进程会等待子进程结束之后再结束 from multiprocessing import Process import os import time import random def func(): time.sleep(random.randint(0,3)) print("run",os.getpid()) if __name__ == '__main__': for i in range(10): p = Process(target=func) p.start() print("主进程ending") # 开启子进程需要消耗时间,print的时间不固定
#!/usr/bin/env python3 # join 阻塞,等待子进程执行结束,在执行主进程后面的代码 from multiprocessing import Process import os import time import random def func(): time.sleep(random.randint(0,3)) print("发送邮件",os.getpid()) if __name__ == '__main__': lst = [] for i in range(10): p = Process(target=func) p.start() lst.append(p) for p in lst:p.join() print("所有已经已经发送完毕!!!")
#!/usr/bin/env python3 # 守护进程 # 守护进程也是一个子进程 # 当主进程的“代码”执行完毕之后自动结束的子进程叫做守护进程 from multiprocessing import Process import time import random import os def func(): while 1: time.sleep(0.3) print("守护进程running",os.getpid()) def play(): time.sleep(random.randint(0,3)) print("子进程running",os.getpid()) if __name__ == '__main__': p = Process(target=func) p.daemon = True # 把子进程设置成守护进程 p.start() lst = [] # 如果有多个子进程 不能在start一个进程之后就立刻join,把所有的进程放到列表中,等待所有进程都start之后再逐一join for i in range(10): p1 = Process(target=play) p1.start() lst.append(p1) for p in lst:p.join() print("主进程ending")
#!/usr/bin/env python3 # 示例火车票 # 问题:多个人同时购买火车票,大家都查到了1张票,进行购买的时候都对同一张 # 火车票进行操作,这样就会存在多人购买同一张火车票的问题。需要对购买操作进行加锁 from multiprocessing import Process,Lock import time import random import os import json dbfile = "./db" def search(): time.sleep(random.random()) with open(dbfile) as f: ret = json.load(f) print("%s:查到%s张票" % (os.getpid(), ret["count"])) def buy(): time.sleep(random.random()) with open(dbfile) as f: ret = json.load(f) if ret["count"] > 0: ret["count"] -= 1 with open(dbfile, "w") as f: json.dump(ret, f) print("\033[31;0m%s:购买1张票\033[0m" % os.getpid()) def run(lock): search() with lock: buy() if __name__ == '__main__': lock = Lock() lst = [] for i in range(10): p = Process(target=run, args=(lock,)) p.start() lst.append(p) for p in lst:p.join() with open(dbfile, "w") as f: dic = {"count": 2} json.dump(dic,f)
#!/usr/bin/env python3 # 信号量是控制锁的数量,信号量的本质是锁+计数器 from multiprocessing import Process,Semaphore import time import random def go_ktv(user, s): with s: print("user%s 进入KTV" % user) time.sleep(random.randint(1, 3)) print("-------->user%s 离开了KTV" % user) if __name__ == '__main__': s = Semaphore(4) lst = [] for i in range(10): p = Process(target=go_ktv, args=(i,s)) p.start() lst.append(p) for p in lst:p.join() print("---打烊了---")
#!/usr/bin/env python3 # 事件内部内置了一个标志 # wait 方法 如果这个标志是True,那么wait == pass # wait 方法 如果这个标志是False,那么wait就会陷入阻塞,一直阻塞到标志从False变成True # 一个事件在创建之初 内部的标志默认是False # False -> True :set() # True -> False :clear() # 红绿灯模型 from multiprocessing import Process, Event import time,random def car(e, n): while True: if not e.is_set(): # 进程刚开启,is_set()的值是False,模拟信号灯为红色 print('\033[31m红灯亮\033[0m,car%s等着' % n) e.wait() # 阻塞,等待is_set()的值变成True,模拟信号灯为绿色 print('\033[32m车%s 看见绿灯亮了\033[0m' % n) time.sleep(random.randint(3, 6)) if not e.is_set(): #如果is_set()的值是Flase,也就是红灯,仍然回到while语句开始 continue print('车开远了,car', n) break def traffic_lights(e, inverval): while True: time.sleep(inverval) # 先睡3秒 if e.is_set(): # 标志是True print('######', e.is_set()) e.clear() # ---->将is_set()的值设置为False else: # 标志是False e.set() # ---->将is_set()的值设置为True print('***********',e.is_set()) if __name__ == '__main__': e = Event() #e就是事件 t = Process(target=traffic_lights, args=(e, 3)) # 创建一个进程控制红绿灯 for i in range(10): p = Process(target=car,args=(e, i)) # 创建是个进程控制10辆车 p.start() t.start() print('============》') # 10个进程 模拟车 :车的行走要依靠当时的交通灯 # 交通灯是绿灯 车就走 # 交通灯是红灯 车就停 停到灯变绿 # wait 来等灯 # set clear 来控制灯
#!/usr/bin/env python3 # 管道 + 锁 == 队列 # 管道也是一个可以实现进程之间通信的模型 # 但是管道没有锁,数据不安全 # 消息中间件 # memcache # rabitmq # kafka —— 大数据相关 # redis # 队列抢票 from multiprocessing import Process,Queue import os def buy(): try: ret = q.get_nowait() print("%s:抢到了%s" %(os.getpid(),ret)) except:pass if __name__ == '__main__': q = Queue() q.put("北京-许昌") lst = [] for i in range(10): p = Process(target=buy) p.start() lst.append(p) for p in lst:p.join() print("shouqin了")
三、线程
#!/usr/bin/env python3 # 什么是进程 :计算机资源分配的最小单位 # 什么是线程 :CPU调度的最小单位 # 多个线程之间的数据时共享的 # 线程和进程的关系 :每一个进程中都至少有一个线程 # python中线程的特点 """ GIL锁 全局解释器锁 解释器的锅 Cpython解释器的问题 在同一个进程中 同一个时刻 只能有一个线程被CPU执行 导致高计算型 代码 不适合用python的多线程来解决 用多进程或者分布式来解决高计算型代码 """ # 启动多个线程 from threading import Thread import time import os import random n = 100 def func(): global n n -= 1 print(n) if __name__ == '__main__': lst = [] for i in range(100): t = Thread(target=func) t.start() lst.append(t) for t in lst:t.join() print("主进程running")
#!/usr/bin/env python3 # 主线程结束了之后守护线程也同时结束 # 守护线程会等待主线程完全结束之后才结束 from threading import Thread import time import os import random def run(): while 1: print("守护进程is running") def func(): time.sleep(random.randint(1,3)) print("子线程is running") if __name__ == '__main__': ts = Thread(target=run) ts.daemon = True ts.start() for i in range(10): t = Thread(target=func) t.start() print("主进程running")
#!/usr/bin/env python3 # 一般情况下开机多进程的个数和线程的个数 """ cpu的个数+1 进程数 cpu的个数*5 线程数 """ # 开启进程线程池 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time def func(i): time.sleep(1) print("%s thread is running" % i) if __name__ == '__main__': t = ThreadPoolExecutor(5) for i in range(20): t.submit(func, i) t.shutdown() # 和join用法一样 print("done")
#!/usr/bin/env python3 # map用法 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import time def func(i): time.sleep(1) print("%s thread is running" % i) if __name__ == '__main__': t = ThreadPoolExecutor(5) t.map(func,range(20)) # map取代了for+submit t.shutdown() # 和join用法一样 print("done")
#!/usr/bin/env python3 from concurrent.futures import ThreadPoolExecutor import time import random # concurrent.futures callback是由子线程做的 # callback回调函数 urls=[ 'https://www.baidu.com', 'https://www.python.org', 'https://www.openstack.org', 'https://help.github.com/', 'http://www.sina.com.cn/', 'http://www.cnblogs.com/', 'http://www.sogou.com/', 'http://www.sohu.com/' ] def get_url(url): time.sleep(random.randint(1,3)) return url def fx_url(res): print(res.result()) if __name__ == '__main__': t = ThreadPoolExecutor(2) for url in urls: t.submit(get_url, url).add_done_callback(fx_url)
四、协程
# 进程 计算机中资源分配的最小单位 开启进程数量:cpu+1 # 线程 CPU 调度最小单位 开启线程数量:cpu*5 # 协程 把一个线程拆分成几个 开启携程数量:500+ # 进程 线程 都是操作系统在调度 # 协程 是程序级别调度 # 减轻了操作系统的负担、增强了用户对程序的可控性 # 安装第三方模块gevent # 示例1 # from gevent import monkey;monkey.patch_all() import gevent import time def eat(name): print('%s eat 1' %name) gevent.sleep(2) print('%s eat 2' %name) def play(name): print('%s play 1' %name) time.sleep(1) print('%s play 2' %name) g1=gevent.spawn(eat,'egon') g2=gevent.spawn(play,name='egon') g1.join() g2.join() # gevent.joinall([g1,g2]) print('主') # 示例2 from gevent import monkey;monkey.patch_all() import gevent import requests import time def get_page(url): print('GET: %s' %url) response=requests.get(url) if response.status_code == 200: print('%d bytes received from %s' %(len(response.text),url)) start_time=time.time() gevent.joinall([ gevent.spawn(get_page,'https://www.python.org/'), gevent.spawn(get_page,'https://www.yahoo.com/'), gevent.spawn(get_page,'https://github.com/'), ]) stop_time=time.time() print('run time is %s' %(stop_time-start_time))