Aiofiles введение



Установка:

pip install aiofiles

Импорт

import aiofiles

Aiofiles(документация) — отличная библиотека для асинхронного скачивания медиа-файлов из интернета. С её помощью мы можем ускорить загрузку файлов и чтение больших текстовых файлов практически в 10 раз. В этом разделе курса мы сравним синхронные и асинхронные способы скачивания изображений и видео с нашего сайта-тренажёра, чтобы наглядно продемонстрировать разницу в скорости.

Aiofiles может работать не только с файлами, которые хранятся на вашем компьютере. Прелесть работы с этой библиотекой заключается в том, что она умеет работать с response.content, а это именно то, что нужно для создания асинхронной загрузки файлов.

Функция open() из aiofiles работает почти так же, как и привычная всем синхронная функция open(), встроенная в Python. Мы можем использовать асинхронную версию функции open() как с менеджером контекста with, так и без него.

С использованием менеджера контекста with:

import aiofiles
import asyncio

#С использованием менеджера контекста with
async with aiofiles.open('filename', mode='r') as f:
    contents = await f.read()
print(contents)

#Результат

    'My file contents'

Без использования менеджера контекста with

file = await aiofiles.open('filename', mode='r')

contents = await file.read()

file.close()

print(contents)

#Результат

    'My file contents'

При использовании асинхронной функции open() из библиотеки aiofiles необходимо закрывать файл с помощью file.close(), если мы не использовали контекстный менеджер with. С применением контекстного менеджера with файл закроется самостоятельно после прочтения.

Асинхронная функция open() имеет такие же атрибуты, как её синхронный аналог.

aiofiles.open(‘folder/file.txt’) — абсолютное или относительное значение пути к файлу;

aiofiles.open(mode=») — необязательный атрибут, который указывает режим работы с файлом

  • mode=»r» — открывает файл только для чтения, установлен по умолчанию;
  • mode=»w» — открывает файл для записи, существующий файл будет перезаписан, а если файл не существует, то он будет создан;
  • mode=»x» — бросает исключение FileExistsError, если файл с таким именем уже существует;
  • mode=»a» — открывает файл для  добавления данных в конец файла;
  • mode=»t» — символ текстового режима;
  • mode=»b» — символ двоичного режима, для записи медиа-файлов;
  • mode=»wb» — открывает файл для записи в бинарном режиме, именно этот режим мы будем использовать для скачивания медиа файлов;

aiofiles.open(buffering=-1) — не обязательный аргумент, используется для политики буферизации;

  • buffering=-1 — значение по умолчанию;
  • buffering=0 — построчная буферизация, только для бинарного режима;
  • buffering=1 — построчная буферизация для текстового файла;

encoding=’utf-8′ — необязательный аргумент, используется для кодирования или декодирования файла, этот аргумент следует использовать только для текстового файла;

errors=None — None по умолчанию, необязательный аргумент, указывает, как должны обрабатываться ошибки кодирования и декодирования, только для текстовых файлов;

  • errors=»strict» — бросает исключение ValueError, то же самое что и None;
  • errors=»ignore» — игнорирует ошибки кодирования, данные могут быть потеряны;
  • errors=»surrogateescape» — любые некорректные байты будут представлены как символы Юникода, при обратной операции символы будут преобразованы обратно в байты;
  • errors=»xmlcharrefreplace» — символы, которые не поддерживаются указанной кодировкой, будут заменены соответствующей ссылкой на символ XML

newline=’None’ — None по умолчанию, определяет работу режима новой строки, только для текстовых файлов;

newline=’\n’:

  • При чтении: Каждый символ \n в файле интерпретируется как конец строки. Это означает, что файл разделяется на строки по каждому встреченному \n. Символы \r читаются как обычные символы и не влияют на разделение строк.
  • При записи: Каждый символ новой строки в строке данных (независимо от того, \n или \r\n) преобразуется в \n перед записью в файл.

newline=’\r’:

  • При чтении: Каждый символ \r в файле интерпретируется как конец строки. Это означает, что файл разделяется на строки по каждому встреченному \r. Символы \n читаются как обычные символы и не влияют на разделение строк.
  • При записи: Каждый символ новой строки в строке данных преобразуется в \r перед записью в файл.

newline=’\r\n’:

  • При чтении: Файл будет разделен на строки на основе последовательности символов ‘\r\n’. То есть каждый раз, когда встречается последовательность ‘\r\n’ в файле, она интерпретируется как конец строки. Если в файле встречаются отдельные символы ‘\n’ или ‘\r’, не составляющие полную последовательность ‘\r\n’, они будут восприниматься как обычные символы текста и не будут вызывать разделение строки.
  • При записи: Каждый символ новой строки в данных, которые вы пишете в файл, будет преобразован в последовательность ‘\r\n’. Это означает, что если ваш текст содержит \n (стандарт для Unix и Linux систем), он будет автоматически преобразован в стиль новой строки Windows (\r\n), когда вы записываете его в файл.

closefd=True — True по умолчанию, если установить False, то файловый дескриптор не будет закрыт даже после команды file.close();

loop=None —  None по умолчанию, если loop отсутствует, будет выбран event loop по умолчанию в соответствии с установленной политикой asyncio.

executor=»name_loop» — принимает экземпляр класса event loop, по умолчанию None, будет выбран цикл событий по умолчанию name_loop = asyncio.get_event_loop();

Aiofiles имеет в своём арсенале асинхронные копии привычных для всех функций чтения и записи файлов: а именно, readline, readlines, write и writelines. О них мы и поговорим ниже. На самом деле функций больше, и познакомиться с ними можно в документации. Для наших целей хватит и перечисленных. Все эти функции должны быть использованы с ключевым словом await, потому что, когда вы работаете с файлами, в момент чтения или записи цикл событий будет переключать контекст для выполнения других задач.

await file.writelines(str) — записывает в файл указанную последовательность строк.

#Этот код генерирует и записывает в файл построчно 100к рандомных чисел от 10к до 100к

import time
import aiofiles
import asyncio
import random

async def write_numbers():
    async with aiofiles.open('one_millon_numbers.txt', mode='a') as file:
        for x in range(1, 100001):
            await file.writelines(str(random.randint(10000, 100000)) + '\n')

start = time.perf_counter()
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(write_numbers())
print(time.perf_counter() - start)

Результат:

    8.32808830001159

await file.write(str) — записывает в файл указанную строку.

# Этот код генерирует и записывает в файл целиком миллион чисел от 100к до 1кк

import time
import aiofiles
import asyncio
async def write_numbers():
    async with aiofiles.open('async_write_one_millon_numbers.txt', mode='w') as file:
        numbers = str([x for x in range(100000, 1100001)])
        await file.write(numbers)
start = time.perf_counter()
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(write_numbers())
print(time.perf_counter() - start)

Результат:

    0.1362756000016816

await file.readlines() — cчитывает из файла все строки в список и возвращает его. Для запуска кода ниже и следующего вам понадобится файл, сгенерированный прошлым кодом.

import time
import aiofiles
import asyncio

# Этот код читает файл построчно миллион строк.
async def gen_numbers():
    async with aiofiles.open('async_one_millon_numbers.txt', mode='r') as file:
        text = await file.readlines()
        print(text)
start = time.perf_counter()
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(gen_numbers())
print(time.perf_counter() - start)

await file.readline() — cчитывает из файла одну строку и возвращает её.

import time
import aiofiles
import asyncio

# Этот код читает из файла всего одну строку.
async def gen_numbers():
    async with aiofiles.open('async_one_millon_numbers.txt', mode='r') as file:
        text = await file.readline()
        print(text)
start = time.perf_counter()
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(gen_numbers())
print(time.perf_counter() - start)


Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: