线程和进程的操作是由程序触发系统接口, 最后的执行者是系统; 协程的操作则是程序员.
协程存在的意义: 对于多线程应用, CPU 通过切片的方式来切换线程间的执行, 线程切换时需要耗时 (保存状态, 下次继续). 协程, 则只使用一个线程, 在一个线程中规定某个代码块执行顺序.
协程的适用场景: 当程序中存在大量不需要 CPU 的操作时 (IO), 适用于协程;
event loop 是协程执行的控制点, 如果你希望执行协程, 就需要用到它们.
event loop 提供了如下的特性:
1, 注册, 执行, 取消延时调用 (异步函数)
2, 创建用于通信的 client 和 server 协议 (工具)
3, 创建和别的程序通信的子进程和协议 (工具)
4, 把函数调用送入线程池中
协程示例一:
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- """
- 协程示例
- """
- import asyncio
- async def test1():
- print("test1, starting")
- await test2()
- print("test1, ending")
- async def test2():
- print("test2 start")
- loop = asyncio.get_event_loop() #asyncio.get_event_loop() : asyncio 启动默认的 event loop
- loop.run_until_complete(test1()) #run_until_complete() : 这个函数是阻塞执行的, 知道所有的异步函数执行完成,
- loop.close() #close() : 关闭 event loop.
greenlet 协程示例:
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- """
- 协程示例
- """
- import greenlet
- def fun1():
- print("12")
- f2.switch()
- print("56")
- f2.switch()
- def fun2():
- print("34")
- f1.switch()
- print("78")
- f1 = greenlet.greenlet(fun1)
- f2 = greenlet.greenlet(fun2)
- f1.switch()
gevent 协程示例:
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- """
- gevent 协程示例
- """
- import gevent
- def fun1():
- print("www.baidu.com") #第一步
- gevent.sleep(0)
- print("end the baidu.com") #第三步
- def fun2():
- print("www.yusheng.com") #第二步
- gevent.sleep(0)
- print("end the yusheng.com") #第四步
- gevent.joinall([
- gevent.spawn(fun1),
- gevent.spawn(fun2),
- ])
示例三: 遇到 IO 操作自动切换:
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- """
- 遇到 IO 操作自动切换:
- """
- import gevent
- import requests
- def fun(url):
- print("get: %s" % url)
- gevent.sleep(0)
- data = requests.get(url)
- ret = data.text
- print(url, len(ret))
- gevent.joinall([
- gevent.spawn(fun, 'https://www.python.org/'),
- gevent.spawn(fun, 'https://www.yahoo.com/'),
- gevent.spawn(fun, 'https://github.com/'),
- ])
来源: http://www.bubuko.com/infodetail-3279586.html