2015-12-21 32 views
2

我不知道是否有任何性能上的明顯的差異foobar之間:Python asyncio:函數或協程,使用哪個?

class Interface: 
    def __init__(self, loop): 
     self.loop = loop 

    def foo(self, a, b): 
     return self.loop.run_until_complete(self.bar(a, b)) 

    async def bar(self, a, b): 
     v1 = await do_async_thing1(a) 
     for i in range(whatever): 
      do_some_syncronous_work(i) 
     v2 = await do_async_thing2(b, v1) 
     return v2 

async def call_foo_bar(loop): 
    a = 'squid' 
    b = 'ink' 
    interface = Interface(loop) 
    v_foo = interface.foo(a, b) 
    v_bar = await interface.bar(a, b) 

,但將使用run_until_complete造成任何實際的,顯着的不同運行我的程序?我想問的是我正在構建一個接口類,它將適應可分解的「後端」,其中一些可能是異步的。我希望使用標準函數用於公共(可重用)方法接口類,因此可以爲所有代碼維護一個API,而不會混淆使用事件循環可用的異步後端)。

更新:我沒有正確檢查代碼,第一個版本是完全無效的,因此重寫。

+0

它實際上取決於。 'Foo'將會同步執行,而'Bar'不會。可能發生的是調度/分配可能很重要,即它可能對最終用戶有所影響。 – freakish

+0

是的,'foo()'是一個阻塞調用。 另外'run_until_complete'不能用已經運行的事件循環調用 –

回答

3

loop.run_until_complete()應使用外協程在最高層。調用run_until_complete()活動(正在運行)事件循環被禁止。

另外loop.run_until_complete(f)是一個阻塞調用:執行線程被阻塞,直到f協程未來變得完成。

async def是通過使併發的協同程序可以相互通信來編寫異步代碼的正確方法。

async def需要運行事件循環(應調用loop.run_until_complete()loop.run_forever())。

+0

好的,所以沒有合理的方法來構建可用於同步代碼和異步代碼的接口。 – SColvin

+0

編號 現在最好的推薦方法是通過在run_until_complete()的幫助下添加使用異步對象的存根函數來構建* async *接口並對其進行* sync * –

0

我不這麼認爲。我已經使用了兩個,並沒有真正看到差異。我更喜歡foo,因爲我已經更多地使用它,理解它會更好一些,但這取決於你。

1

有一個世界的不同。這是一個SyntaxError在正常功能def功能中使用await

import asyncio 

async def atest(): 
    print("hello") 

def test(): 
    await atest() 

async def main(): 
    await atest() 
    test() 

-

File "test.py", line 9 
    await atest() 
      ^
SyntaxError: invalid syntax 
+0

是的,但正如解釋讓我們假設我們從協程中調用它們的東西(協程或函數)。 – SColvin

+0

不,這是一個'SyntaxError'不管是什麼。你可以輕鬆地爲自己嘗試。 –

+0

是的你是對的,我提交問題之前沒有檢查代碼的壞處。我會更新這個問題。 – SColvin

相關問題