2017-07-31 82 views
1

在同一個python項目中使用asyncio和線程是否合理,以便代碼在不同的線程中運行,其中一些asyncio用於獲取順序查找的異步活動代碼?使用asyncio和線程

或會試圖做到這一點意味着我錯過了關於使用線程或asyncio的一些基本概念?

+0

相關:[線程](http://asyncio.readthedocs.io/en/latest/threads.html)來自[asyncio用戶文檔](http://asyncio.readthedocs.io/en/latest/index的.html)。 – Vincent

回答

1

確定它可能是有道理的。

異步代碼原則上在同一個線程中運行一堆例程。

這意味着此刻一個例程必須等待輸入或輸出(I/O),將暫時停止該例程並簡單地開始處理另一個例程,直到遇到一個等待在那裏,等等

多線程代碼原則上在您機器的不同核心上運行,同時

在同一個程序中使用它們可能會很有意義。使用asyncio爲了在等待I/O時繼續處理。例如,使用多線程可以在程序的另一部分中並行執行大量計算。

0

我不明白你在問什麼(關於「按順序查看異步活動代碼」的一部分),但由於沒有答案,我會寫一些想法。

讓我們來談談爲什麼我們需要asyncio/threads。想象一下,我們有一個任務來提出兩個請求。

  1. 如果我們將使用普通的一個線程非異步代碼,只是我們 選擇是使請求一個URL,而且只要完成後 - 爲 另:

    request(url1) 
    request(url2) 
    

    問題這裏是我們做的工作效率低下:每個功能在執行的大部分時間都不會等待網絡結果。如果我們以某種方式能夠使用CPU進行第二次請求,而第一次使用CPU而不需要它,那將會很酷。

  2. 這個問題可以通過在不同的線程中運行的功能來解決(通常可以解決):

    with ThreadPoolExecutor(max_workers=2) as e: 
        e.submit(request, url1) 
        e.submit(request, url2) 
    

    我們會得到更快的結果這樣。當第一個請求被網絡阻塞時,CPU將能夠爲另一個線程中的第二個請求做一些有用的事情。然而,這不是理想的解決方案:線程之間的切換具有一定的成本,執行流程比第一個示例更復雜。

    應該有更好的方法。

  3. 使用一個功能空閒時間開始執行另一個功能是一般什麼ASYNCIO:

    await asyncio.gather(
        async_request(url1), 
        async_request(url2), 
    ) 
    

    事件循環管理執行流程:當第一個協程到達一些I/O操作和CPU可以用來在別處做工作,第二個協程開始。稍後的事件循環返回,以保持第一個協程的執行。

    我們得到「並行」請求和清晰可理解的代碼。由於我們在單線程中並行化,所以我們不需要另一個線程。

實際上,當我們使用asyncio線程仍然可以是有用的。如果我們願意爲他們支付,他們可以help我們投同步I/O功能,非常快速異步:

async def async_request(url): 
    loop = asyncio.get_event_loop() 
    return (await loop.run_in_executor(None, request, url)) 

但同樣,這是可選的,我們通常可以找到模塊發出請求(和其他I/O任務)異步無線程。

當線程在異步程序中很有用時,我沒有面對任何其他任務。

+0

這是在算法交易的情況下,我使用Intectivity經紀人的Python TWS API(如果我理解正確的話)在除主代碼之外的其他線程上進行回調。我是python的新手,並試圖找出在環境中做東西的最佳方式,並且混淆了多個線程和asyncIO(在單個線程中運行)之間的關係。 – epeleg