Как запустить код блокировки независимо от цикла asyncio

Мой проект требует, чтобы я запускал блокирующий код (из другой библиотеки), продолжая при этом цикл 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). Это как бы работает, если есть вещи, которые нужно сделать после blocking_code() внутри main(); но blocking_code() — это последняя функция в main(), и это приведет к паузе всего цикла while до тех пор, пока не завершится blocking_code(), прежде чем начать сначала.

Я не знаю, возможно ли это, и если да, то как это делается; но идеальный сценарий таков.

Запустите main(), затем запустите blocking_code() в своем собственном экземпляре. Как будто выполняется другой файл .py. Таким образом, как только цикл достигает blocking_code() в main(), он запускает файл blocking_code.py, и пока выполняется скрипт blocking_code.py, циклы while снова продолжаются сверху.

Если к моменту 2-го прохода цикла while он снова достигает blocking_code(), а предыдущий запуск не завершен; другой экземпляр blocking_code() будет работать в своем собственном экземпляре независимо.

Имеет ли смысл то, что я говорю? Возможно ли добиться желаемого результата?

Благодарю вас!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это возможно с помощью нитей. Таким образом, вы не блокируете свой основной цикл, вам нужно обернуть поток в задачу asyncio. Вы можете дождаться возвращаемых значений после завершения цикла, если вам это нужно. Вы можете сделать это с помощью комбинации asyncio.create_task и asyncio.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

Другие вопросы по теме