利用几个独立进程multiprocessing 进行通信,实现队列的效果,dish_queue.join() 进程结束的标志
import multiprocessing as mp def washer(dishes,output): for dish in dishes: print ('Washing',dish,'dish') output.put(dish) def dryer(input): while True: dish = input.get() print ('Dryin',dish,'dish') input.task_done() dish_queue = mp.JoinableQueue() dryer_proc = mp.Process(target =dryer,args=(dish_queue,)) dryer_proc.daemon = True dryer_proc.start() dishes = ['salad','bread','entree','dessert'] washer(dishes,dish_queue) dish_queue.join()线程的解释,运行在进程的内部,可以访问进程的所有的内容,multiprocessing和threading两个模块分别代表了进程和线程,感觉量级别的不同 使用线程完成进程的操作
import threading def do_sth(what): whoami(what) def whoami(what): print ('Thread %s says %s '%(threading.current_thread(),what)) if __name__ =="main": whoami("I am the main program") for i in range(4): p = threading.Thread(target=do_sth,args=("I am function %s"%n)) p.start()使用线程完成洗盘子的功能,dishes_queue 表示生成队列,dryer_thread = threading.thread()表示 定义一个线程
import threading,queue import time def washer(dishes,dish_queue): for dish in dishes: print ('Washing',dish) time.sleep(5) dish_queue.put(dish) def drydish(dish_queue): while True: dish = dish_queue.get() print ("Drying",dish) dish_queue.task_done() dish_queue = queue.Queue() for i in range(2): dryer_thread = threading.Thread(target=dryer,args=(dish_queue,)) dryer_thread.start() #队列定义dish_queue, dishes = ['salad','bread','entree','desert'] washer(dishes,dish_queue) dish_queue.join()线程和进程之间的不同,线程没有终止函数,一个运行中的线程很难终止,并且线程之间没有共享的全局变量, 线程和进程之间的关系是可以使用”房间+幽灵”的方式解释的,线程是房间,进程是幽灵,房间中的物件是变量, 在处理有全局变量的线程时,需要在县城修改变量之前使用到”软件锁”,这样子在修改的时候,其他的进程也需要等待,锁可以嵌套,也别忘记解锁!
11.1.4 绿色线程和gevent 开发者把程序中运行速度比较慢的部分开始划分成多个线程或者是多个进程,比如Apache Web服务器,还有另外一种方法 基于事件编程,一个基于事件的程序会循环一个核心事件循环,比如Nginx Web,现在介绍 gevent 库,主要功能是把普通代码转换成”协程” “协程”的解释:类似于一个相互通信的生成器,它们会自己记录自己的位置,然后修改python很多的标准对象,比如socket,使他们使用自己的机制避免阻塞,但是“协程”没有办法处理C 写的python扩展代码
利用gevent模块gevent.spawn函数 创建一个微线程(绿色线程),微线程和普通线程区别在于,微线程不会阻塞,如果遇到阻塞, gevent 是可以把控制权切换到别的绿色线程上的
import gevent from gevent import socket hosts = ['www.crappytaxidermy.com','wwww.walterpottertaxidermy.com','www.antique-taxidermy.com'] jobs = [gevent.spawn(gevent.socket.gethostbyname,host)for host in hosts] #等待所有任务完成的函数joinall() gevent.joinall(jobs,timeout=5) for job in jobs: print (job.value)使用猴子补丁(monkey-patching)函数可以修改标准模块,比如socket,让他们直接使用微线程,而不是通过 spawn的方式 进行使用了微线程,把下面的代码加在开头就可以充分利用gevent 带来的速度提升!
import gevent, from gevent import monkey;monkey,patch_all()gevent 对于大型网站有明显的加速作用,还有两个流行的事件驱动是tornado 和 gunicorn,他们都是 使用底层事件处理和加速 web服务器 ,如果 你使用的是传统的web服务器比如Apache 就可以 上面 两个 事件驱动 进行构建高速网站
11.1.5 异步事件驱动的网络框架 twisted 把函数关联到具体的事件上去,当事件发生的时候就会被调用函数,这种方式成为“回调”,
11.1.7 利用 Redis 服务器 创建一个队列 利用python模块把 数据添加 到一个 dish队列 中 ,这个 dish队列 用 conn = redis.Redis() 生成的 ,增加多个Dryer.py进程 ,使用 os.getpid()的方式获得 进程识别码 ,multiprocessing.Process(target=dryer) 表示同时创建多个进程 进行工作
11.1.8 使用 队列的 控制层 具体的可以看一下 celery 包 ,里面使用了 multiprocessing,gevent等 方法
11.2 跨空间的分布式计算(网络化) 11.2.2 不同模式进行搭建网络化应用 “请求–响应”/“客户端–服务器端”,该模式是同步的,客户端会一直等待服务器端的响应 “推送”/“扇出”,数据请求发送到进程池,等有空的工作进程进行处理 “ ”
