Python高级知识归纳

匿名 (未验证) 提交于 2019-12-02 22:51:08

本文主要归纳3个内容:

  1. Python协程
  2. Python多线程
  3. Python多进程

本部分内容参考:廖雪峰 - Python协程

  • 协程,又称微线程,纤程。英文名Coroutine
  • 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。(不同于函数调用)
  • 协程相对于多线程的优势:
    • 协程的执行效率高于多线程
    • 协程不需要锁机制:因为只有一个线程,所以不存在同时写变量冲突
  • 多进程+协程,既充分利用多核CPU,又充分发挥协程的高效率,可获得极高的性能

【示例】生产者消费者模型的协程实现:

def consumer():     r = ''     while True:         n = yield r         if not n:             return         print('[CONSUMER] Consuming %s...' % n)         r = '200 OK'  def produce(c):     c.send(None)     n = 0     while n < 5:         n = n + 1         print('[PRODUCER] Producing %s...' % n)         r = c.send(n)         print('[PRODUCER] Consumer return: %s' % r)     c.close()  c = consumer() produce(c)

执行结果:

[PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK

注意到consumer函数是一个generator,把一个consumer传入produce后:

  • 首先调用c.send(None)启动生成器;

  • 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

  • consumer通过yield拿到消息,处理,又通过yield把结果传回

  • produce拿到consumer处理的结果,继续生产下一条消息;

  • produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

  • Python中使用asyncio实现协程:
import threading import asyncio  @asyncio.coroutine def hello():     print('Hello world! (%s)' % threading.currentThread())     yield from asyncio.sleep(1)     print('Hello again! (%s)' % threading.currentThread())  loop = asyncio.get_event_loop() tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()

执行结果:

Hello world! (<_MainThread(MainThread, started 140735195337472)>) Hello world! (<_MainThread(MainThread, started 140735195337472)>) (暂停约1秒) Hello again! (<_MainThread(MainThread, started 140735195337472)>) Hello again! (<_MainThread(MainThread, started 140735195337472)>)

hello()会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。

由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。

把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。

为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。

请注意,async和await是针对coroutine的新语法,要使用新的语法,只需要做两步简单的替换:

  • 把@asyncio.coroutine替换为async;
  • 把yield from替换为await。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!