#python #python-asyncio
Вопрос:
Каков шаблон проектирования для записи в несколько файлов с использованием asyncio
?
Вот краткое изложение однопоточной версии того, что я хочу сделать.
import datetime
import json
def generate_records():
for i in range(100):
# simulate some JSON content that I want to write to a file
# assume that this takes some significant amount of time
yield {
'index':index,
'message':f"Message {index}",
'timestamp':datetime.datetime.now().isoformat()
}
for (i,r) in enumerate(generate_records()):
with open(f"record_{i:04}.json", 'w') as fout:
json.dump(r, fout)
Как можно использовать asyncio
для записи этих файлов одновременно с созданием записей?
Комментарии:
1.
asyncio
следует использовать с циклом событий, чтобы один поток мог асинхронно принимать запросы на запись в разные файлы (что считается медленным вводом-выводом). Видишь codeflex.co/python3-async-await-example/?amp2. Асинхронная запись на один и тот же диск не повышает общую производительность.
3. @yoonghm цель состоит в том, чтобы иметь возможность записывать на диск одновременно с повторением данных. Я постарался сделать пример простым, чтобы он был сосредоточен на части asyncio. Обновлено, чтобы лучше отразить то, к чему я клоню.
4. @yoonghm: На самом деле это может быть, по крайней мере, для вращающихся дисков; если в ОС несколько записей в очереди, она может изменить их порядок, чтобы они записывались по порядку, поскольку головка диска выполняет один проход изнутри наружу диска (или наоборот). Представьте, что на диске были дорожки ABCDEFGH изнутри наружу; если головка диска находится в точке A, а вы одновременно записываете в B, D и F, он может выполнять запись за одно сканирование. Последовательные записи в F, затем в, затем D приводят к увеличению задержки поиска. По общему признанию, за исключением
sync
вызовов, ОС обычно кэширует записи и в любом случае переупорядочивает их, но возможно улучшение производительности.5. @ShadowRanger, технология дисководов настигла меня. Спасибо
Ответ №1:
import json
import datetime
import aiofiles
async def main():
def mk_record(index):
# simulate some JSON content that I want to write to a file
return {
'index': index,
'message': f"Message {index}",
'timestamp': datetime.datetime.now().isoformat()
}
records = [mk_record(i) for i in range(100)]
async def write_record(i, r):
# Test by pretending the write takes a while
# Delete this line for actual code.
await asyncio.sleep(1)
async with aiofiles.open(f'/tmp/record_{i:04}.json', mode='w') as fout:
await fout.write(json.dumps(r))
await asyncio.gather(*[write_record(i, r) for i, r in enumerate(records)])
if __name__ == '__main__':
asyncio.run(main())
Комментарии:
1. Ух. Извините. В моем первоначальном ответе была ошибка, и мне пришлось ее исправить. Запись записей все еще происходила одна за другой. Я понял, что должен изменить его так, чтобы написание каждой записи было отдельной задачей. Исправлено выше.