Как идиоматически завершить операцию 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 (и, следовательно, добавить в цикл событий). Затем в вашем ридере вы можете записать в файл, если вам нужен постоянный журнал. Я понимаю, что обсуждение вопроса о том, как избежать периодического сна, выходит за рамки этого вопроса, и я не хочу вдаваться в подробности, чем я, но вы попросите подсказки о том, как лучше всего подходить к асинхронному программированию.

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