簡體   English   中英

如何獨立於異步循環運行阻塞代碼

[英]How to run a blocking code independently from asyncio loop

我的項目要求我運行阻塞代碼(來自另一個庫),同時繼續我的 asyncio while: true 循環。 代碼看起來像這樣:

async def main():
    while True:
        session_timeout = aiohttp.ClientTimeout()
        async with aiohttp.ClientSession() as session:
            
            // Do async stuffs like session.get and so on
            
            # At a certain point, I have a blocking code that I need to execute
            
            // Blocking_code() starts here. The blocking code needs time to get the return value.
               Running blocking_code() is the last thing to do in my main() function.
            
            # My objective is to run the blocking code separately. 
            # Such that whilst the blocking_code() runs, I would like my loop to start from the beginning again,
            # and not having to wait until blocking_code() completes and returns.
            # In other words, go back to the top of the while loop.
            
            # Separately, the blocking_code() will continue to run independently, which would eventually complete
            # and returns. When it returns, nothing in main() will need the return value. Rather the returned
            # result continue to be used in blocking_code()

asyncio.run(main())

我試過使用pool = ThreadPool(processes=1)thread = pool.apply_async(blocking_code, params) 如果在 main() 中的 blocking_code() 之后需要完成一些事情,它就可以工作; 但是 blocking_code() 是 main() 中的最后一件事,它會導致整個 while 循環暫停,直到 blocking_code() 完成,然后再從頂部開始。

我不知道這是否可行,如果可行,它是如何實現的; 但理想的情況是這樣的。

運行 main(),然后在它自己的實例中運行 blocking_code()。 就像執行另一個 .py 文件一樣。 因此,一旦循環到達 main() 中的 blocking_code(),它就會觸發 blocking_code.py 文件,並且在 blocking_code.py 腳本運行時,while 循環再次從頂部繼續。

如果在 while 循環的第 2 次通過時,它再次到達 blocking_code() 且之前的運行尚未完成; blocking_code() 的另一個實例將在其自己的實例上獨立運行。

我說的有道理嗎? 是否有可能達到預期的結果?

謝謝!

這可以通過線程實現。 所以你不會阻塞你的主循環,你需要將你的線程包裝在一個 asyncio 任務中。 如果需要,您可以在循環完成后等待返回值。 您可以結合使用asyncio.create_taskasyncio.to_thread

import aiohttp
import asyncio
import time

def blocking_code():
    print('Starting blocking code.')
    time.sleep(5)
    print('Finished blocking code.')

async def main():
    blocking_code_tasks = []

    while True:
        session_timeout = aiohttp.ClientTimeout()
        async with aiohttp.ClientSession() as session:
        
            print('Executing GET.')
            result = await session.get('https://www.example.com')
        
            blocking_code_task = asyncio.create_task(asyncio.to_thread(blocking_code))
            blocking_code_tasks.append(blocking_code_task)

    #do something with blocking_code_tasks, wait for them to finish, extract errors, etc.

asyncio.run(main())

上面的代碼運行線程中的阻塞代碼,然后將其放入異步任務中。 然后我們將其添加到blocking_code_tasks列表以跟蹤所有當前正在運行的任務。 稍后,您可以使用asyncio.gather類的方法獲取值或錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM