Python asyncio: как заставить две бесконечные (с while True) асинхронные функции работать одновременно?

Мне нужно, чтобы несколько функций работали одновременно и бесконечно. Я планирую использовать для этого asyncio и, если возможно, хочу избежать прямого использования цикла событий.

Я попробовал этот код:

import asyncio
import os


class Program:
    def __init__(self):
        self.files = os.listdir('data')
        self.last_file = ''
        self.history = []

    async def wait_new_file(self):
        await self._wait_new_file()

    def _wait_new_file(self):
        while True:
            checked_files = set(os.listdir('data'))
            if new_file := checked_files.difference(set(self.files)):
                print(f'{new_file = }')
                self.last_file = list(new_file)[0]
                self.files.append(list(new_file)[0])
                self.history.append(f'>>>{self.files[-1]}')
                print(f'{self.files = }')
            if deleted_file := set(self.files).difference(checked_files):
                print(f'{deleted_file = }')
                self.files.remove(list(deleted_file)[0])
                print(f'{self.files = }')
            if os.path.exists('stop'):
                print(self.history)
                return

    async def check_difference(self):
        await self._check_difference()

    def _check_difference(self):
        flip = True
        while True:
            if flip and os.path.exists('flip'):
                flip = False
                print('on')
            if not flip and not os.path.exists('flip'):
                flip = True
                print('off')
            if os.path.exists('stop'):
                return

    async def main(self):
        async with asyncio.TaskGroup() as tg:
            task_check_difference = tg.create_task(self.check_difference())
            task_monitor_files = tg.create_task(self.wait_new_file())

program = Program()
asyncio.run(program.main())

Но при этом Task_monitor_files не делает никакой работы, подскажите пожалуйста, что там не так?

вы никогда не приостанавливаете, поэтому у другой задачи никогда не будет возможности запуститься, вам следует добавлять await asyncio.sleep(0) после каждых, скажем, 100 итераций (измерьте это и настройте это) внутри вашего цикла while, чтобы другая задача получила шанс, попробуйте это

python_user 06.08.2024 06:07

Вероятно, в вашей файловой системе есть гораздо лучшие средства наблюдения за файлами, где ОС будет уведомлять вашу программу, если какой-либо файл изменится, вместо того, чтобы постоянно читать весь каталог снова и снова.

deceze 06.08.2024 07:21

Методы _wait_new_file и _check_difference следует определять как асинхронные методы, поскольку у них есть операторы return и то, что они возвращают, т. е. None, не является сопрограммой. Вы получите исключение, когда они вернутся: TypeError: объект NoneType нельзя использовать в выражении ожидания.

Booboo 06.08.2024 12:53
Почему в 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
3
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ваша проблема в том, как вы используете asyncio и await

В методах _wait_new_file и _check_difference вы используете циклы while True, которые блокируют некоторый код. Когда вы вызываете await self._wait_new_file() или await self._check_difference(), выполнение застрянет в этом цикле и никогда не вернется.

Чтобы это исправить, вам следует сделать эти методы асинхронными, используя asyncio.sleep() вместо ожидания занятости.

Вот лучшая версия вашего кода:

import asyncio
import os


class Program:
    def __init__(self):
        self.files = os.listdir('data')
        self.last_file = ''
        self.history = []

    async def wait_new_file(self):
        while True:
            ... # ur code
            await asyncio.sleep(1)  # wait for 1 second before checking again

    async def check_difference(self):
        flip = True
        while True:
            ... # ur code
            await asyncio.sleep(1)  # wait for 1 second before checking again

    async def main(self):
        async with asyncio.TaskGroup() as tg:
            task_check_difference = tg.create_task(self.check_difference())
            task_monitor_files = tg.create_task(self.wait_new_file())

program = Program()
asyncio.run(program.main())

Надеюсь, что это поможет вам.

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