Asyncio для записи файлов - PullRequest
0 голосов
/ 25 мая 2020

Я только что закончил читать пару руководств по Asyncio of Real Python, в которых объясняется, что asyncio (и многопоточность) отлично подходят для процессов, связанных с вводом-выводом. В учебниках в основном используются функции asyncio.sleep () и asynchronous session.get (url) модуля aiohttps для представления «работы» ввода-вывода, которую мы хотели бы передать другим задачам во время их выполнения.

Я увидел привязку ввода-вывода и подумал попробовать записать файлы большого размера sh, идея заключалась в том, чтобы сократить время, необходимое для записи 10 больших файлов, путем их асинхронного запуска, а не синхронного, поскольку мы остались ожидание, пока записывается каждый файл. Я думал, что это будет похоже на получение ответа от session.get (url) в контексте файловой системы. Однако я не могу получить никаких преимуществ в производительности по сравнению с синхронной записью файлов, поэтому я либо неправильно реализовал асинхронную запись файлов (с использованием aiofile), либо неправильно понял, что запись файлов не может быть реализована асинхронно - мое первое предположение поскольку это было то, что существует максимальная скорость / емкость записи файла, и это уже достигнуто, когда выполняется первая задача. Третья возможность заключается в том, что она реализована правильно, но в этом случае занимает больше времени, чем синхронная реализация, но я считаю это маловероятным.

Ниже приведен код, который я написал для сравнения синхронной и асинхронной реализации записи большого файла. Любая помощь, объясняющая, где я ошибся в реализации или понимании, была бы потрясающей.

Импорт

import asyncio
from aiofile import AIOFile
from codetiming import Timer

Синхронная запись в файл

def write_file(text):
    with open('somefile.txt', 'w') as file:
        print(f'Writing file {text[:20]}')
        file.write(text)

def main_sync():
    timer = Timer(text=f"Task elapsed time: {{:.1f}}")
    timer.start()
    for text in [
        "http://google.com",
        "http://yahoo.com",
        "http://linkedin.com",
        "http://apple.com",
        "http://microsoft.com",
        "http://facebook.com",
        "http://twitter.com",
    ]:
        print(f"Task writing file: {text[:20]}")
        write_file(text*40000000)
    timer.stop()

Асинхронный c Файл Написание

async def aio_file_write(text):
    async with AIOFile("somefile.txt", 'w') as file:
        print(f'Writing file {text[:20]}')
        await file.write(text)
        await file.fsync()

async def task(name, work_queue):
    timer = Timer(text=f"Task {name} elapsed time: {{:.1f}}")
    while not work_queue.empty():
        text = await work_queue.get()
        print(f"Task {name} writing file: {text[:20]}")
        timer.start()
        await aio_file_write(text)
        timer.stop()

async def main():
    work_queue = asyncio.Queue()

    for text in [
        "http://google.com",
        "http://yahoo.com",
        "http://linkedin.com",
        "http://apple.com",
        "http://microsoft.com",
        "http://facebook.com",
        "http://twitter.com",
    ]:
        await work_queue.put(text*40000000)

    with Timer(text="\nTotal elapsed time: {:.1f}"):
        await asyncio.gather(
            asyncio.create_task(task("One", work_queue)),
            asyncio.create_task(task("Two", work_queue)),
        )

Скрипт

if __name__== "__main__":
asyncio.run(main())

else:
main_sync()
...