Ввод/вывод текста, двоичных и необработанных потоков.
Модуль io
предоставляет основные средства Python для работы с различными типами ввода-вывода. Существует три основных типа ввода-вывода: Text I/O -
текстовый ввод-вывод, Binary I/O
двоичный ввод-вывод и Raw I/O - необработанный ввод-вывод. Конкретный объект, принадлежащий любой из этих категорий, называется
файловым объектом.
Независимо от своей категории каждый конкретный объект потока также будет иметь различные возможности: он может быть доступен только для чтения, только для записи или для чтения и записи. Он также может разрешать произвольный произвольный доступ (поиск вперед или назад в любом месте) или только последовательный доступ в случае сокета или канала.
Содержание:
Text I/O
- текстовый ввод-вывод:
Текстовый ввод/вывод ожидает и производит
объекты типа str
. Это означает, что каждый раз, когда хранилище изначально состоит из байтов, например в случае файла, кодирование и декодирование данных выполняется прозрачно, а также учитывается необязательный перевод специфичных для платформы символов новой строки.
fp = open("myfile.txt", "r", encoding="utf-8")
fp = io.StringIO("some initial text data")
API текстового потока подробно описан в документации по
io.TextIOBase
.
Binary I/O
- двоичный ввод-вывод:
Двоичный ввод/вывод, также называемый буферизованным вводом/выводом ожидает объекты, похожие на байты, и создает
объекты типа bytes
. Кодирование, декодирование или перевод новой строки не выполняется. Эта категория потоков может использоваться для всех видов нетекстовых данных, а также когда требуется ручное управление обработкой текстовых данных.
fp = open("myfile.jpg", "rb")
fp = io.BytesIO(b"some initial binary data: \x00\x01")
API двоичного потока подробно описан в документации по
io.BufferedIOBase
. Другие модули могут предоставлять дополнительные способы создания текстовых или двоичных потоков.
Raw I/O
- необработанный ввод-вывод:
Необработанный ввод/вывод, также называемый небуферизованным вводом/выводом обычно используется как низкоуровневый строительный блок для двоичных и текстовых потоков. Очень редко встречается необходимость напрямую манипулировать необработанным потоком из пользовательского кода. Тем не менее, вы можете создать необработанный поток, открыв файл в двоичном режиме mode='rb'
с отключенной буферизацией buffering=0
:
fp = open("myfile.jpg", "rb", buffering=0)
API необработанного потока подробно описан в документации по
io.RawIOBase
.
Кодировка текста.
Многие разработчики не указывают кодировку при открытии текстовых файлов, закодированных в UTF-8 (например, JSON, TOML, Markdown и т. д.), так как в Unix по умолчанию используют локаль UTF-8. НО, для большинства пользователей Windows, это вызывает ошибки, так как кодировка локали не является UTF-8. Например:
# Может не работать в Windows, если в
# файле есть символы, отличные от ASCII.
with open("README.md") as f:
long_description = f.read()
Кроме того, хотя пока нет конкретного плана, Python может изменить кодировку текстового файла по умолчанию на UTF-8 в будущем.
Соответственно, настоятельно рекомендуется явно указывать кодировку при открытии текстовых файлов. Если необходимо использовать UTF-8, то нужно передавать encoding='utf-8'
. Чтобы использовать текущую кодировку языкового стандарта, то Python 3.10 поддерживает передачу аргумента encoding='locale'
.
Если нужно запустить существующий код в Windows, который пытается открыть файлы UTF-8 с использованием кодировки локали по умолчанию, то можно включить режим UTF-8.
Включение EncodingWarning
.
Новое в Python 3.10
Чтобы найти, где в коде используется кодировка локали по умолчанию, можно включить
параметр командной строки -X warn_default_encoding
или установить
переменную среды PYTHONWARNDEFAULTENCODING
, которая будет выдавать предупреждение
EncodingWarning
при использовании кодировки по умолчанию.
Если код предоставляет API, который использует функцию
open()
или
io.TextIOWrapper
и при этом передает
encoding=None
в качестве аргумента, то можно использовать функцию
io.text_encoding()
, чтобы вызывающие API генерировали
EncodingWarning
, если они не передают кодировку.
Для новых API, необходимо рассматривать возможность использования UTF-8 по умолчанию (т.е. encoding='utf-8'
).