[英]How is this a coroutine?
我試圖理解Python中的協同程序(一般而言)。 一直在閱讀關於理論,概念和一些例子,但我仍然在苦苦掙扎。 我理解異步模型(做了一些Twisted)但不是協同程序。
一個教程將此作為一個協程示例(我做了一些更改來說明我的問題):
async def download_coroutine(url, number):
"""
A coroutine to download the specified url
"""
request = urllib.request.urlopen(url)
filename = os.path.basename(url)
print("Downloading %s" % url)
with open(filename, 'wb') as file_handle:
while True:
print(number) # prints numbers to view progress
chunk = request.read(1024)
if not chunk:
print("Finished")
break
file_handle.write(chunk)
msg = 'Finished downloading {filename}'.format(filename=filename)
return msg
這與此一起運行
coroutines = [download_coroutine(url, number) for number, url in enumerate(urls)]
completed, pending = await asyncio.wait(coroutines)
查看生成器協同程序示例,我可以看到一些yield
語句。 這里什么也沒有,urllib是同步的,AFAIK。
此外,由於代碼應該是異步的,我期待看到一系列交錯的數字。 (1,4,5,1,2,......,“完成”,......)。 我所看到的是一個單一的數字重復結束在一個Finished
,然后另一個(3,3,3,3,......“完成”,1,1,1,1,......,“完成”。 ..)。
在這一點上,我很想說教程是錯誤的,這只是一個協程,因為前面有異步。
在協程 共同代表合作 。 屈服(對其他例程)使例程成為一個共同例程,實際上,因為只有在等待時才能讓其他協同例程交錯。 在Python 3.5及更高版本的新async
世界中,通常是通過await
來自其他協同程序的結果來實現的。
根據該定義,您找到的代碼不是協程。 就Python而言,它是一個協程對象 ,因為這是使用async def
創建的函數對象的類型。
所以,是的,教程是無益的,因為他們在協程函數中使用了完全同步的,不合作的代碼。
而不是urllib
,將需要異步HTTP庫。 像aiohttp
:
import aiohttp
async def download_coroutine(url):
"""
A coroutine to download the specified url
"""
filename = os.path.basename(url)
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
with open(filename, 'wb') as fd:
while True:
chunk = await resp.content.read(1024)
if not chunk:
break
fd.write(chunk)
msg = 'Finished downloading {filename}'.format(filename=filename)
return msg
在等待建立連接時,以及等待更多網絡數據時,以及再次關閉會話時,此協程可以產生其他例程。
我們可以進一步使文件寫入異步,但這有可移植性問題 ; aiofiles
項目庫使用線程來卸載阻塞調用。 使用該庫,代碼需要更新為:
import aiofiles
async with aiofiles.open(filename, 'wb') as fd:
while True:
chunk = await resp.content.read(1024)
if not chunk:
break
await fd.write(chunk)
注意 :此博客帖子已更新以解決這些問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.