Как идиоматически завершить операцию Asyncio в Python
Я работаю над кодом, где у меня есть длинная команда оболочки, чей вывод отправляется на диск. Эта команда сгенерирует сотни ГБ на файл. Я успешно написал код, который вызывает эту команду асинхронно и успешно возвращает управление (ожидает) для ее завершения.
У меня также есть код, который может асинхронно читать этот файл во время его записи, чтобы я мог обрабатывать содержащиеся в нем данные. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу найти способ остановить программу чтения файлов после завершения команды оболочки.
Я думаю, что я ищу какое-то прерывание, которое я могу передать в свою функцию записи после завершения команды оболочки, которую я могу использовать, чтобы сказать ей закрыть файл и завершить цикл обработки событий.
Вот моя функция писателя. Сейчас он работает вечно, ожидая записи новых данных в файл.
import asyncio
PERIOD = 0.5
async def readline(f):
while True:
data = f.readline()
if data:
return data
await asyncio.sleep(PERIOD)
async def read_zmap_file():
with open('/data/largefile.json'
, mode = 'r+t'
, encoding = 'utf-8'
) as f:
i = 0
while True:
line = await readline(f)
print('{:>10}: {!s}'.format(str(i), line.strip()))
i += 1
loop = asyncio.get_event_loop()
loop.run_until_complete(read_zmap_file())
loop.close()
Если мой подход выключен, пожалуйста, дайте мне знать. Я относительно новичок в асинхронном программировании. Любая помощь будет оценена.
1 ответ
Итак, я бы сделал что-то вроде
reader = loop.create_task(read_zmap_file)
Затем в своем коде, который управляет процессом оболочки после выхода из процесса оболочки, вы можете сделать
reader.cancel()
Ты можешь сделать
loop.run_until_complete(reader)
В качестве альтернативы вы можете просто установить флаг где-нибудь и использовать этот флаг в своем выражении while. Вам не нужно использовать примитивы asyncio, когда что-то более простое работает.
Тем не менее, я бы посмотрел, как ваш читатель может избежать периодического сна. если ваш читатель сможет не отставать от команды оболочки, я бы порекомендовал канал, потому что каналы можно использовать с select (и, следовательно, добавить в цикл событий). Затем в вашем ридере вы можете записать в файл, если вам нужен постоянный журнал. Я понимаю, что обсуждение вопроса о том, как избежать периодического сна, выходит за рамки этого вопроса, и я не хочу вдаваться в подробности, чем я, но вы попросите подсказки о том, как лучше всего подходить к асинхронному программированию.