io — потоки введення/виведення

Цей модуль містить додаткові типи об’єктів stream (файлоподібних) та допоміжні функції. Він надає вбудовану функцію open(), а також буфери тексту та двійкових даних у пам’яті (StringIO, BytesIO), що реалізують стандартний інтерфейс потоку read/write/seek.

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

Відмінність від CPython

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

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

Важлива дихотомія в CPython — буферизовані та небуферизовані потоки. У MicroPython усі потоки наразі небуферизовані. Це пов’язано з тим, що всі сучасні ОС, і навіть багато RTOS та драйверів файлової системи вже виконують буферизацію на своєму боці. Додавання ще одного рівня буферизації є контрпродуктивним (це відома проблема «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

Повернути поточний вміст базового буфера.