![](/img/trans.png)
[英]How to generalize a function call which may be async, tornado coroutine, or normal?
[英]Call an async function in an normal function
我對python 3.6的asyncio很新
所以問題是我有一個類,我想在那里初始化一些屬性。 其中一個屬性是異步函數的返回值。
這樣做的最佳做法是什么?
在init函數中調用event_loop一次以獲取返回值?
使__init__函數異步? 並在事件循環中運行它?
干杯!
再次更新:以下是我的代碼:
import asyncio import aioredis from datetime import datetime class C: def __init__(self): self.a = 1 self.b = 2 self.r = None asyncio.get_event_loop().run_until_complete(self._async_init()) async def _async_init(self): # this is the property I want, which returns from an async function self.r = await aioredis.create_redis('redis://localhost:6379') async def heart_beat(self): while True: await self.r.publish('test_channel', datetime.now().__str__()) await asyncio.sleep(10) def run(self): asyncio.get_event_loop().run_until_complete(self.heart_beat()) c=C() c.run()
在init函數中調用event_loop一次以獲取返回值?
如果在__init__
期間旋轉事件循環,則在事件循環運行時將無法實例化C
; asyncio事件循環不嵌套 。
[ 編輯:在問題的第二次更新之后,事件循環似乎由非靜態方法C.run
,因此__init__
run_until_complete
將與編寫的代碼一起使用。 但是這種設計是有限的 - 例如,它不允許在事件循環運行時構造C
或類C
另一個實例。
使
__init__
函數異步? 並在事件循環中運行它?
如果不訴諸非常丑陋的黑客, __init__
不能異步。 Python的__init__
按副作用運行,必須返回None
,而async def
函數返回一個協程對象。
要使這項工作,你有幾個選擇:
C
工廠 創建一個返回C
實例的異步函數,例如:
async def make_c():
c = C()
await c._async_init()
return c
這樣的函數可以沒有問題地異步,並且可以根據需要等待。 如果您更喜歡靜態方法到函數,或者如果您感覺不舒服從類中未定義的函數訪問私有方法,則可以使用make_c()
替換C.create()
。
Cr
字段 你可以簡單地通過在其中存儲Future
來使r
屬性異步:
class C:
def __init__(self):
self.a = 1
self.b = 2
loop = asyncio.get_event_loop()
# note: no `await` here: `r` holds an asyncio Task which will
# be awaited (and its value accessed when ready) as `await c.r`
self.r = loop.create_task(aioredis.create_redis('redis://localhost:6379'))
這將要求每次使用cr
拼寫為await cr
。 這是否可接受(或甚至是有益的)取決於程序中其他地方使用的位置和頻率。
C
構造函數 雖然__init__
不能異步,但這個限制並不適用於它的低級表親__new__
。 T.__new__
可以返回任何對象,包括一個甚至不是T
實例的對象,我們可以使用它來返回一個協程對象:
class C:
async def __new__(cls):
self = super().__new__(cls)
self.a = 1
self.b = 2
self.r = await aioredis.create_redis('redis://localhost:6379')
return self
# usage from another coroutine
async def main():
c = await C()
# usage from outside the event loop
c = loop.run_until_complete(C())
最后一種方法是我不建議用於生產代碼的,除非你有充分的理由使用它。
C
實例的C.__new__
構造函數; C.__init__
; await C()
看起來非慣用,甚至(或特別)對於習慣於asyncio的人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.