io — потоки ввода/вывода

Этот модуль содержит дополнительные типы объектов stream (файлоподобных) и вспомогательные функции. Он предоставляет встроенную функцию open(), а также текстовые и двоичные буферы в памяти (StringIO, BytesIO), которые реализуют стандартный потоковый интерфейс read/write/seek.

Концептуальная иерархия

Отличие от CPython

Концептуальная иерархия базовых классов потоков в MicroPython упрощена, как описано в этом разделе.

(Абстрактные) базовые классы потоков, которые служат основой поведения всех конкретных классов, в CPython придерживаются нескольких дихотомий (попарных классификаций). В MicroPython они несколько упрощены и сделаны неявными для достижения более высокой эффективности и экономии ресурсов.

Важной дихотомией в CPython является различие между небуферизованными и буферизованными потоками. В MicroPython все потоки в настоящее время небуферизованы. Это связано с тем, что все современные ОС и даже многие ОСРВ и драйверы файловых систем уже выполняют буферизацию на своей стороне. Добавление ещё одного уровня буферизации контрпродуктивно (проблема, известная как «bufferbloat») и расходует драгоценную память. Обратите внимание, что всё же бывают случаи, когда буферизация может быть полезна, поэтому в дальнейшем мы можем добавить опциональную поддержку буферизации.

Но в CPython другая важная дихотомия связана с «буферизованностью» — это вопрос о том, может ли поток допускать короткие чтения/записи или нет. Короткое чтение — это когда пользователь запрашивает, например, 10 байт из потока, но получает меньше; аналогично для записи. В CPython небуферизованные потоки автоматически подвержены коротким операциям, тогда как буферизованные гарантируют отсутствие таковых. Отсутствие коротких чтений/записей — важное свойство, поскольку оно позволяет разрабатывать более лаконичные и эффективные программы — нечто весьма желательное для MicroPython. Поэтому, хотя MicroPython не поддерживает буферизованные потоки, он всё же обеспечивает потоки без коротких операций. Будут короткие операции или нет, зависит от потребностей каждого конкретного класса, но разработчикам настоятельно рекомендуется предпочитать поведение без коротких операций по причинам, изложенным выше. Например, сокеты MicroPython гарантированно избегают коротких чтений/записей. На самом деле в настоящее время в ядре нет ни одного примера класса потока с короткими операциями, и такой класс был бы специфичен для конкретного оборудования.

Поведение без коротких операций становится непростым в случае неблокирующих потоков, причём блокирующее и неблокирующее поведение — это ещё одна дихотомия CPython, полностью поддерживаемая MicroPython. Неблокирующие потоки никогда не ждут поступления или записи данных — они читают/записывают всё, что возможно, или сигнализируют об отсутствии данных (или возможности записать данные). Очевидно, что это конфликтует с политикой «без коротких операций», и действительно, случай неблокирующих буферизованных (и при этом без коротких операций) потоков запутан в CPython — в некоторых местах такое сочетание запрещено, в некоторых оно не определено или просто не документировано, а в некоторых случаях вызывает многословные исключения. В MicroPython дело обстоит гораздо проще: неблокирующие потоки важны для эффективных асинхронных операций, поэтому это свойство преобладает над свойством «без коротких операций». Так, блокирующие потоки будут по возможности избегать коротких чтений/записей (единственный случай короткого чтения — это достижение конца файла или ошибка (но ошибки не возвращают короткие данные, а вызывают исключения)), тогда как неблокирующие потоки могут возвращать короткие данные, чтобы избежать блокировки операции.

Последняя дихотомия — это двоичные и текстовые потоки. MicroPython, разумеется, поддерживает их, но если в CPython текстовые потоки по своей природе буферизованы, то в MicroPython это не так. (И это действительно один из случаев, для которых мы можем добавить поддержку буферизации.)

Обратите внимание, что в целях эффективности MicroPython не предоставляет абстрактных базовых классов, соответствующих приведённой выше иерархии, и реализовать или унаследовать класс потока на чистом Python невозможно.

Функции

io.open(name: str, mode: str = 'r', **kwargs) Any

Открывает файл. Встроенная функция open() является псевдонимом этой функции. Параметр mode поддерживается всегда; поддержка других аргументов может различаться.

Классы

class io.IOBase

Базовый класс для объектов потока («файлоподобных»). Конкретные подклассы реализуют низкоуровневые методы ввода-вывода, приведённые ниже (readinto, write, ioctl); среда выполнения строит на их основе более высокоуровневый потоковый протокол (read, readline, readlines, close, итерация), так что каждый экземпляр потока поддерживает эти методы, даже если подкласс их не определяет.

Методы реализации (переопределяйте их в подклассе):

readinto(buf: bytearray) int | None

Читает байты в доступный для записи буфер buf. Возвращает количество прочитанных байтов, 0 в конце потока или None, если данных в данный момент нет (для неблокирующего потока).

write(buf: bytes) int | None

Записывает байты из buf. Возвращает количество записанных байтов или None, если запись в данный момент не может быть выполнена (для неблокирующего потока).

ioctl(request: int, arg: int) int

Управляет нижележащим потоком/устройством. request — один из кодов запроса MP_STREAM_*. Возвращает неотрицательное значение при успехе или отрицательное значение errno при ошибке.

Методы потокового протокола (доступны для каждого экземпляра потока):

read(size: int = -1)

Читает и возвращает до size байтов (или символов в текстовом режиме). Если size опущен или отрицателен, читает до конца потока. Возвращает bytes для двоичных потоков и str для текстовых потоков; пустой результат означает конец потока.

readline(size: int = -1)

Читает и возвращает одну строку, включая завершающий символ новой строки, если он присутствует. Если задан size, читается не более size байтов (или символов). Возвращает пустые bytes / str в конце потока.

readlines() list

Читает до конца потока и возвращает list строк, каждая с её завершающим символом новой строки.

close() None

Закрывает поток и освобождает все нижележащие ресурсы. Операции над закрытым потоком вызывают OSError (или ValueError для потоков в памяти).

seek(offset: int, whence: int = 0) int

Изменяет текущую позицию в потоке на offset байтов относительно whence (0 = начало потока, 1 = текущая позиция, 2 = конец потока). Возвращает новую абсолютную позицию. Вызывает OSError для потока, не поддерживающего перемещение.

tell() int

Возвращает текущую абсолютную позицию в потоке. Эквивалентно seek(0, 1).

flush() None

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

Прямая итерация потока выдаёт по одной строке за итерацию — эквивалентно вызову readline() в цикле до возврата признака конца потока в виде пустой строки. Поток также поддерживает протокол менеджера контекста, так что with open(...) as f: закрывает поток автоматически.

Примечание

Модуль потоков MicroPython также предоставляет C-помощники с суффиксом «1» mp_stream_read1_obj, mp_stream_readinto1_obj и mp_stream_write1_obj, которые выполняют один нижележащий вызов ввода-вывода вместо цикла до полного удовлетворения запроса. Они используются внутренне такими классами, как machine.UART, для реализации собственных read / write — но ни один стандартный класс потока не привязывает их в качестве вызываемых из Python методов read1 / readinto1 / write1.

class io.StringIO(string: str = '')

Файлоподобный объект в памяти для ввода/вывода в текстовом режиме (аналогично обычному файлу, открытому с модификатором «t»). Начальное содержимое можно задать параметром string (который должен быть обычной строкой). Экземпляры также поддерживают протокол менеджера контекста (можно использовать в инструкции with).

read(size: int = -1) str

Читает и возвращает до size символов. Если size опущен или отрицателен, читает и возвращает всё оставшееся содержимое.

readline(size: int = -1) str

Читает и возвращает одну строку. Если задан size, читается не более size символов.

readinto(buf: bytearray) int

Читает в предварительно выделенный доступный для записи буфер buf и возвращает количество прочитанных байтов.

write(s: str) int

Записывает строку s и возвращает количество записанных символов.

seek(offset: int, whence: int = 0) int

Изменяет позицию в потоке на offset относительно whence (0 = начало, 1 = текущая, 2 = конец) и возвращает новую абсолютную позицию.

tell() int

Возвращает текущую позицию в потоке.

flush() None

Сбрасывает буферы записи. Для потока в памяти не выполняет никаких действий.

close() None

Закрывает поток и освобождает нижележащий буфер. Дальнейшие операции над закрытым потоком вызывают ValueError.

getvalue() str

Возвращает текущее содержимое нижележащего буфера.

class io.StringIO(alloc_size: int)

Создаёт пустой объект StringIO, заранее выделенный для хранения до alloc_size байтов, так что запись до этого количества байтов не приведёт к перевыделению буфера (избегая ситуации нехватки памяти или её фрагментации). Этот конструктор является расширением MicroPython, рекомендуемым только для особых случаев и системных библиотек, но не для пользовательских приложений.

Отличие от CPython

Этот конструктор является расширением MicroPython.

read(size: int = -1) str

Читает и возвращает до size символов. Если size опущен или отрицателен, читает и возвращает всё оставшееся содержимое.

readline(size: int = -1) str

Читает и возвращает одну строку. Если задан size, читается не более size символов.

readinto(buf: bytearray) int

Читает в предварительно выделенный доступный для записи буфер buf и возвращает количество прочитанных байтов.

write(s: str) int

Записывает строку s и возвращает количество записанных символов.

seek(offset: int, whence: int = 0) int

Изменяет позицию в потоке на offset относительно whence (0 = начало, 1 = текущая, 2 = конец) и возвращает новую абсолютную позицию.

tell() int

Возвращает текущую позицию в потоке.

flush() None

Сбрасывает буферы записи. Для потока в памяти не выполняет никаких действий.

close() None

Закрывает поток и освобождает нижележащий буфер. Дальнейшие операции над закрытым потоком вызывают ValueError.

getvalue() str

Возвращает текущее содержимое нижележащего буфера.

class io.BytesIO(string: bytes = b'')

Файлоподобный объект в памяти для ввода/вывода в двоичном режиме (аналогично обычному файлу, открытому с модификатором «b»). Начальное содержимое можно задать параметром string (который должен быть объектом bytes). Экземпляры также поддерживают протокол менеджера контекста (можно использовать в инструкции with).

read(size: int = -1) bytes

Читает и возвращает до size байтов. Если size опущен или отрицателен, читает и возвращает всё оставшееся содержимое.

readline(size: int = -1) bytes

Читает и возвращает одну строку. Если задан size, читается не более size байтов.

readinto(buf: bytearray) int

Читает в предварительно выделенный доступный для записи буфер buf и возвращает количество прочитанных байтов.

write(b: bytes) int

Записывает байтоподобный объект b и возвращает количество записанных байтов.

seek(offset: int, whence: int = 0) int

Изменяет позицию в потоке на offset относительно whence (0 = начало, 1 = текущая, 2 = конец) и возвращает новую абсолютную позицию.

tell() int

Возвращает текущую позицию в потоке.

flush() None

Сбрасывает буферы записи. Для потока в памяти не выполняет никаких действий.

close() None

Закрывает поток и освобождает нижележащий буфер. Дальнейшие операции над закрытым потоком вызывают ValueError.

getvalue() bytes

Возвращает текущее содержимое нижележащего буфера.

class io.BytesIO(alloc_size: int)

Создаёт пустой объект BytesIO, заранее выделенный для хранения до alloc_size байтов, так что запись до этого количества байтов не приведёт к перевыделению буфера (избегая ситуации нехватки памяти или её фрагментации). Этот конструктор является расширением MicroPython, рекомендуемым только для особых случаев и системных библиотек, но не для пользовательских приложений.

Отличие от CPython

Этот конструктор является расширением MicroPython.

read(size: int = -1) bytes

Читает и возвращает до size байтов. Если size опущен или отрицателен, читает и возвращает всё оставшееся содержимое.

readline(size: int = -1) bytes

Читает и возвращает одну строку. Если задан size, читается не более size байтов.

readinto(buf: bytearray) int

Читает в предварительно выделенный доступный для записи буфер buf и возвращает количество прочитанных байтов.

write(b: bytes) int

Записывает байтоподобный объект b и возвращает количество записанных байтов.

seek(offset: int, whence: int = 0) int

Изменяет позицию в потоке на offset относительно whence (0 = начало, 1 = текущая, 2 = конец) и возвращает новую абсолютную позицию.

tell() int

Возвращает текущую позицию в потоке.

flush() None

Сбрасывает буферы записи. Для потока в памяти не выполняет никаких действий.

close() None

Закрывает поток и освобождает нижележащий буфер. Дальнейшие операции над закрытым потоком вызывают ValueError.

getvalue() bytes

Возвращает текущее содержимое нижележащего буфера.