Мне нужно, чтобы несколько функций работали одновременно и бесконечно. Я планирую использовать для этого 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 не делает никакой работы, подскажите пожалуйста, что там не так?
Вероятно, в вашей файловой системе есть гораздо лучшие средства наблюдения за файлами, где ОС будет уведомлять вашу программу, если какой-либо файл изменится, вместо того, чтобы постоянно читать весь каталог снова и снова.
Методы _wait_new_file
и _check_difference
следует определять как асинхронные методы, поскольку у них есть операторы return
и то, что они возвращают, т. е. None
, не является сопрограммой. Вы получите исключение, когда они вернутся: TypeError: объект NoneType нельзя использовать в выражении ожидания.
Ваша проблема в том, как вы используете 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())
Надеюсь, что это поможет вам.
вы никогда не приостанавливаете, поэтому у другой задачи никогда не будет возможности запуститься, вам следует добавлять
await asyncio.sleep(0)
после каждых, скажем, 100 итераций (измерьте это и настройте это) внутри вашего цикла while, чтобы другая задача получила шанс, попробуйте это