pythonasync
Ⅰ python什麼時候用async await
然而並不會有更多的人因此換到Python 3。他們會說,不就是一點語法糖么,兼容性都保證不了其他再多功能又有什麼用。
Ⅱ python裡面有類似npm裡面的async的庫嗎
Disclaimer: 以下對比可能有強烈的個人色彩
Node.js > Python 的地方
快:這個快有兩方面,第一是V8引擎快,在V8引擎背後操刀的是Lars Bak大神,他創造過高性能SmallTalk引擎和Java Hotspot引擎(現在Java的默認VM),他帶領下的V8引擎讓Javascript速度達到了一個新的階段。第二是非同步執行,Node.js功能上是一個基於V8引擎的非同步網路和IO Library,和Python的Twisted很像,不同的是Node.js的event loop是很底層的深入在語言中的,可以想像成整個文件在執行的時候就在一個很大的event loop里。
npm:npm可以說是用起來最順手的package management了,npm作為Node.js的官方package management,匯集了整個社區最集中的資源。不像Python經歷過easy_install和pip,還有2to3的問題。
Ⅲ 怎麼看:Python 3.5 支持 async/await
換湯不換葯,但專有關鍵字也許會比借用 yield from 的語義更明確。
個人不看好 asyncio
系的一點是官方似乎完全沒有考慮(或沒有引導)大量現有民間庫該如何兼容(或遷移),甚至連 3.5 標准庫的 smtpd 等都還是 2.x
遺留的實現。asyncio 還只是個裸殼子。(不過這個似乎也是官方推廣 Python 3 過程中一貫不負責任的作風,現有的利用 six 庫兼容
2.7+ / 3.2+ 的攻略也是民間總結出來的,官方此前推薦是那個完全沒有可用性的 lib2to3)
Ⅳ 如何看待 Python 3.5支持Async/Await非同步編程
根據Python增強提案(PEP) 第0492號, Python 3.5將通過async和await語法增加對協程的支持。該提案目的是使協程成為Python語言的原生特性,並「建立一種普遍、易用的非同步編程思維模型。」
這個新提議中聲明一個協程的語法如下:
async def read_data(db):
pass
async是明確將函數聲明為協程的關鍵字,即便沒有使用await表達式。這樣的函數執行時會返回一個協程對象。
在協程函數內部,可在某個表達式之前使用await關鍵字來暫停協程的執行,以等待某進程完成:
async def read_data(db):
data = await db.fetch('SELECT ...')
...
由於增強版生成器的存在,Python中其實早已有了協程的形式,例如當yield或yield from聲明在Python生成器內部出現,該生成器就會被當作協程。
以下示例展示基於生成器的協程的用法:
>>> def createGenerator():
... mylist = range(3)
... for i in mylist:
... yield i*i
...
>>> mygenerator = createGenerator()
>>> for i in mygenerator:
... print(i)
0
1
4
以上代碼中,每當生成器在for循環中被調用,該生成器中的for循環就會返回一個新的值。
關於await用法的更多示例請參見上文提到的PEP #0492.
這個關於協程的新提案想明確地把生成器與協程區分開,這么做有如下好處:
使這兩個概念對新開發者來說更易於理解,因為它們二者的語法並不一樣;
能消除由於重構時不小心移除了協程中的yield聲明而導致的「不明確錯誤」,這會導致協程變成普通的生成器。
- async def read_data(db):
- data = await db.fetch('SELECT ...')
- if (data...)
- await api.send(data ...')
async/await語法能讓程序員以序列方式編寫代碼,但編譯器則會將其當作一系列的協程來處理,從而實現有效的並發。回到我們之前的例子,async/await使我們可以順序地編寫多個await聲明語句,就好像每個語句都會阻塞並等待結果,但實際上這並不會導致任何阻塞:
Ⅳ python async=False錯誤如何修改
你使用的是Python3,而async是Python3中加入的關鍵字,關鍵字是不可以作為變數名的。回所以拋出答了一個語法錯誤(SyntaxError)。
這種情況常見做法是加一個下劃線,如:
async_=False
這樣它就是一個普通的變數名而不是關鍵字了。
或者給這個變數換個名字。
PS: 實際上加下劃線也就是換名字。。
Ⅵ python 3.6 async 有什麼用
Python 3.5中引入了async和await,不建議將這兩個名稱用作變數名、類名、函數名和模塊名。它們將在Python 3.7中正式成為關鍵字。
Ⅶ 如何用python寫一個協程
再寫一個任務函數
import asyncio
async def outer():
print('in outer')
print('waiting for result1')
result1 = await phase1()
print('waiting for result2')
result2 = await phase2(result1)
return (result1, result2)
async def phase1():
print('in phase1')
return 'result1'
async def phase2(arg):
print('in phase2')
return 'result2 derived from {}'.format(arg)
event_loop = asyncio.get_event_loop()
try:
return_value = event_loop.run_until_complete(outer())
print('return value: {!r}'.format(return_value))
finally:
event_loop.close()
Ⅷ Python用asyncio模塊做協程非同步IO爬蟲功能,為啥我這兩個模塊下的代碼錯誤這么多!
隨著node.js的盛行,相信大家今年多多少少都聽到了非同步編程這個概念。Python社區雖然對於非同步編程的支持相比其他語言稍顯遲緩,但是也在Python3.4中加入了asyncio,在Python3.5上又提供了async/await語法層面的支持,剛正式發布的Python3.6中asynico也已經由臨時版改為了穩定版。下面我們就基於Python3.4+來了解一下非同步編程的概念以及asyncio的用法。
什麼是協程
通常在Python中我們進行並發編程一般都是使用多線程或者多進程來實現的,對於計算型任務由於GIL的存在我們通常使用多進程來實現,而對與IO型任務我們可以通過線程調度來讓線程在執行IO任務時讓出GIL,從而實現表面上的並發。
其實對於IO型任務我們還有一種選擇就是協程,協程是運行在單線程當中的「並發」,協程相比多線程一大優勢就是省去了多線程之間的切換開銷,獲得了更大的運行效率。Python中的asyncio也是基於協程來進行實現的。在進入asyncio之前我們先來了解一下Python中怎麼通過生成器進行協程來實現並發。
example1
我們先來看一個簡單的例子來了解一下什麼是協程(coroutine),對生成器不了解的朋友建議先看一下Stackoverflow上面的這篇高票回答。
Ⅸ 用Python3 的 asyncio 開發的應用有哪些好的部署方案
你要安裝 python3.4 ,asyncio是Python 3.4版本引入的標准庫,直接內置了對非同步IO的支持。 例子 https://github.com/michaelliao/learn-python3/blob/master/samples/async/async_hello.py import [email protected] hello(): print(...
Ⅹ python非同步有哪些方式
yield相當於return,他將相應的值返回給調用next()或者send()的調用者,從而交出了CPU使用權,而當調用者再次調用next()或者send()的時候,又會返回到yield中斷的地方,如果send有參數,還會將參數返回給yield賦值的變數,如果沒有就和next()一樣賦值為None。但是這里會遇到一個問題,就是嵌套使用generator時外層的generator需要寫大量代碼,看如下示例:
注意以下代碼均在Python3.6上運行調試
#!/usr/bin/env python# encoding:utf-8def inner_generator():
i = 0
while True:
i = yield i if i > 10: raise StopIterationdef outer_generator():
print("do something before yield")
from_inner = 0
from_outer = 1
g = inner_generator()
g.send(None) while 1: try:
from_inner = g.send(from_outer)
from_outer = yield from_inner except StopIteration: breakdef main():
g = outer_generator()
g.send(None)
i = 0
while 1: try:
i = g.send(i + 1)
print(i) except StopIteration: breakif __name__ == '__main__':
main()041
為了簡化,在Python3.3中引入了yield from
yield from
使用yield from有兩個好處,
1、可以將main中send的參數一直返回給最里層的generator,
2、同時我們也不需要再使用while循環和send (), next()來進行迭代。
我們可以將上邊的代碼修改如下:
def inner_generator():
i = 0
while True:
i = yield i if i > 10: raise StopIterationdef outer_generator():
print("do something before coroutine start") yield from inner_generator()def main():
g = outer_generator()
g.send(None)
i = 0
while 1: try:
i = g.send(i + 1)
print(i) except StopIteration: breakif __name__ == '__main__':
main()
執行結果如下:
do something before coroutine start123456789101234567891011
這里inner_generator()中執行的代碼片段我們實際就可以認為是協程,所以總的來說邏輯圖如下:
我們都知道Python由於GIL(Global Interpreter Lock)原因,其線程效率並不高,並且在*nix系統中,創建線程的開銷並不比進程小,因此在並發操作時,多線程的效率還是受到了很大制約的。所以後來人們發現通過yield來中斷代碼片段的執行,同時交出了cpu的使用權,於是協程的概念產生了。在Python3.4正式引入了協程的概念,代碼示例如下:
import asyncio# Borrowed from http://curio.readthedocs.org/en/latest/tutorial.html[email protected] countdown(number, n):
while n > 0:
print('T-minus', n, '({})'.format(number)) yield from asyncio.sleep(1)
n -= 1loop = asyncio.get_event_loop()
tasks = [
asyncio.ensure_future(countdown("A", 2)),
asyncio.ensure_future(countdown("B", 3))]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()12345678910111213141516
示例顯示了在Python3.4引入兩個重要概念協程和事件循環,
通過修飾符@asyncio.coroutine定義了一個協程,而通過event loop來執行tasks中所有的協程任務。之後在Python3.5引入了新的async & await語法,從而有了原生協程的概念。
async & await
在Python3.5中,引入了aync&await 語法結構,通過」aync def」可以定義一個協程代碼片段,作用類似於Python3.4中的@asyncio.coroutine修飾符,而await則相當於」yield from」。
先來看一段代碼,這個是我剛開始使用async&await語法時,寫的一段小程序。
#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time
async def wait_download(url):
response = await requets.get(url)
print("get {} response complete.".format(url))
async def main():
start = time.time()
await asyncio.wait([
wait_download("http://www.163.com"),
wait_download("http://www.mi.com"),
wait_download("http://www.google.com")])
end = time.time()
print("Complete in {} seconds".format(end - start))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
這里會收到這樣的報錯:
Task exception was never retrieved
future: <Task finished coro=<wait_download() done, defined at asynctest.py:9> exception=TypeError("object Response can't be used in 'await' expression",)>
Traceback (most recent call last):
File "asynctest.py", line 10, in wait_download
data = await requests.get(url)
TypeError: object Response can't be used in 'await' expression123456
這是由於requests.get()函數返回的Response對象不能用於await表達式,可是如果不能用於await,還怎麼樣來實現非同步呢?
原來Python的await表達式是類似於」yield from」的東西,但是await會去做參數檢查,它要求await表達式中的對象必須是awaitable的,那啥是awaitable呢? awaitable對象必須滿足如下條件中其中之一:
1、A native coroutine object returned from a native coroutine function .
原生協程對象
2、A generator-based coroutine object returned from a function decorated with types.coroutine() .
types.coroutine()修飾的基於生成器的協程對象,注意不是Python3.4中asyncio.coroutine
3、An object with an await method returning an iterator.
實現了await method,並在其中返回了iterator的對象
根據這些條件定義,我們可以修改代碼如下:
#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time
async def download(url): # 通過async def定義的函數是原生的協程對象
response = requests.get(url)
print(response.text)
async def wait_download(url):
await download(url) # 這里download(url)就是一個原生的協程對象
print("get {} data complete.".format(url))
async def main():
start = time.time()
await asyncio.wait([
wait_download("http://www.163.com"),
wait_download("http://www.mi.com"),
wait_download("http://www.google.com")])
end = time.time()
print("Complete in {} seconds".format(end - start))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())27282930
好了現在一個真正的實現了非同步編程的小程序終於誕生了。
而目前更牛逼的非同步是使用uvloop或者pyuv,這兩個最新的Python庫都是libuv實現的,可以提供更加高效的event loop。
uvloop和pyuv
pyuv實現了Python2.x和3.x,但是該項目在github上已經許久沒有更新了,不知道是否還有人在維護。
uvloop只實現了3.x, 但是該項目在github上始終活躍。
它們的使用也非常簡單,以uvloop為例,只需要添加以下代碼就可以了
import asyncioimport uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())123