Python协程:从yield/send到async/await
這個文章理好了脈落。
http://python.jobbole.com/86069/
我練 習(xí)了一番,感受好了很多。。。
Python由于眾所周知的GIL的原因,導(dǎo)致其線程無法發(fā)揮多核的并行計(jì)算能力(當(dāng)然,后來有了multiprocessing,可以實(shí)現(xiàn)多進(jìn)程并行),顯得比較雞肋。既然在GIL之下,同一時刻只能有一個線程在運(yùn)行,那么對于CPU密集的程序來說,線程之間的切換開銷就成了拖累,而以I/O為瓶頸的程序正是協(xié)程所擅長的:
多任務(wù)并發(fā)(非并行),每個任務(wù)在合適的時候掛起(發(fā)起I/O)和恢復(fù)(I/O結(jié)束)
弄清楚了asyncio.coroutine和yield from之后,在Python3.5中引入的async和await就不難理解了:可以將他們理解成asyncio.coroutine/yield from的完美替身。當(dāng)然,從Python設(shè)計(jì)的角度來說,async/await讓協(xié)程表面上獨(dú)立于生成器而存在,將細(xì)節(jié)都隱藏于asyncio模塊之下,語法更清晰明了。
#!/usr/bin/env python # -*- coding: utf-8 -*-import asyncio import time import random''' def old_fib(n):res = [0] * nindex = 0a = 0b = 1while index < n:res[index] = ba, b = b, a + bindex += 1return resprint("-"*10 + "test old fib " + "-"*10) for fib_res in old_fib(20):print(fib_res)def fib(n):index = 0a = 0b = 1while index < n:yield ba, b = b, a + bindex += 1print("-"*10 + "test yield fib " + "-"*10) for fib_res in fib(20):print(fib_res)def stupid_fib(n):index = 0a = 0b = 1while index < n:sleep_cnt = yield bprint("let me think {0} secs".format(sleep_cnt))time.sleep(sleep_cnt)a, b = b, a + bindex += 1 print("-"*10 + "test yield send " + "-"*10) N = 20 sfib = stupid_fib(N) fib_res = next(sfib) while True:print(fib_res)try:fib_res = sfib.send(random.uniform(0, 0.5))except StopIteration:breakdef copy_fib(n):print("I am copy from fib")yield from fib(n)print("copy end") print("-"*10 + "test yield from " + "-"*10) for fib_res in copy_fib(20):print(fib_res)def copy_stupid_fib(n):print("I am copy from stupid fib")yield from stupid_fib(n)print("Copy end")print("-"*10 + "test yield from and send" + "-"*10) N = 20 csfib = copy_stupid_fib(N) fib_res = next(csfib) while True:print(fib_res)try:fib_res = csfib.send(random.uniform(0, 0.5))except StopIteration:break@asyncio.coroutine def smart_fib(n):index = 0a = 0b = 1while index < n:sleep_secs = random.uniform(0, 0.2)yield from asyncio.sleep(sleep_secs)print("Smart one think {} secs to get {}".format(sleep_secs, b))a, b = b, a + bindex += 1@asyncio.coroutine def stupid_fib(n):index = 0a = 0b = 1while index < n:sleep_secs = random.uniform(0, 0.4)yield from asyncio.sleep(sleep_secs)print("Stupid one think {} secs to get {}".format(sleep_secs, b))a, b = b, a + bindex += 1loop = asyncio.get_event_loop() tasks = [asyncio.async(smart_fib(10)),asyncio.async(stupid_fib(10)),] loop.run_until_complete(async.wait(tasks)) print("All fib finished.") loop.close()'''async def smart_fib(n):index = 0a = 0b = 1while index < n:sleep_secs = random.uniform(0, 0.2)await asyncio.sleep(sleep_secs)print("Smart one think {} secs to get {}".format(sleep_secs, b))a, b = b, a + bindex += 1async def stupid_fib(n):index = 0a = 0b = 1while index < n:sleep_secs = random.uniform(0, 0.4)await asyncio.sleep(sleep_secs)print("Stupid one think {} secs to get {}".format(sleep_secs, b))a, b = b, a + bindex += 1loop = asyncio.get_event_loop() tasks = [asyncio.async(smart_fib(10)),asyncio.async(stupid_fib(10)),] loop.run_until_complete(asyncio.wait(tasks)) print("All fib finished.") loop.close()Python中的協(xié)程經(jīng)歷了很長的一段發(fā)展歷程。其大概經(jīng)歷了如下三個階段:
總結(jié)
以上是生活随笔為你收集整理的Python协程:从yield/send到async/await的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 题解汇总
- 下一篇: 金额大小写转换(1)