io.md
1> **Источник:** https://python-all.ru/2.7/library/io.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 15.2. [`io`](https://python-all.ru/2.7/library/io.html#module-io) – основные инструменты для работы с потоками89Новое в версии 2.6.1011Модуль [`io`](https://python-all.ru/2.7/library/io.html#module-io) предоставляет интерфейсы Python для работы с потоками. В Python 2.x он предлагается как альтернатива встроенному объекту [`file`](https://python-all.ru/2.7/library/functions.html#file), но в Python 3.x это интерфейс по умолчанию для доступа к файлам и потокам.1213> **Примечание**14>15> Поскольку этот модуль разрабатывался в первую очередь для Python 3.x, следует знать, что все упоминания «bytes» в этом документе относятся к типу [`str`](https://python-all.ru/2.7/library/functions.html#str) (псевдонимом которого является `bytes`), а все упоминания «text» относятся к типу [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode). Кроме того, эти два типа не взаимозаменяемы в API [`io`](https://python-all.ru/2.7/library/io.html#module-io).1617На вершине иерархии ввода-вывода находится абстрактный базовый класс [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase). Он определяет базовый интерфейс для работы с потоком. Однако следует отметить, что между чтением и записью в потоке нет разделения; реализации могут возбуждать исключение [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError), если они не поддерживают данную операцию.1819Расширением [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase) является [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), который занимается просто чтением и записью сырых байтов в поток. [`FileIO`](https://python-all.ru/2.7/library/io.html#io.FileIO) наследует [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), чтобы обеспечить интерфейс к файлам в файловой системе машины.2021[`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) занимается буферизацией на сыром байтовом потоке ([`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase)). Его подклассы, [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter), [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader) и [`BufferedRWPair`](https://python-all.ru/2.7/library/io.html#io.BufferedRWPair), буферизуют потоки, которые доступны для чтения, записи, а также для чтения и записи одновременно. [`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom) предоставляет буферизированный интерфейс к потокам с произвольным доступом. [`BytesIO`](https://python-all.ru/2.7/library/io.html#io.BytesIO) – это простой поток байтов в памяти.2223Другой подкласс [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase), [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase), работает с потоками, чьи байты представляют текст, и обрабатывает кодирование и декодирование из строк [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode) и в них. [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper), который расширяет его, является буферизированным текстовым интерфейсом к буферизированному сырому потоку ([`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase)). Наконец, [`StringIO`](https://python-all.ru/2.7/library/io.html#io.StringIO) – это поток в памяти для текста в кодировке Unicode.2425Имена аргументов не являются частью спецификации, и только аргументы [`open()`](https://python-all.ru/2.7/library/io.html#io.open) предназначены для использования в качестве именованных аргументов.2627## 15.2.1. Интерфейс модуля2829#### `io.DEFAULT_BUFFER_SIZE`3031Целое число, содержащее размер буфера по умолчанию, используемый классами буферизованного ввода-вывода модуля. [`open()`](https://python-all.ru/2.7/library/io.html#io.open) использует blksize файла (получаемый с помощью [`os.stat()`](https://python-all.ru/2.7/library/os.html#os.stat)), если это возможно.3233#### `io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)`3435Открывает *file* и возвращает соответствующий поток. Если файл не может быть открыт, возбуждается исключение [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).3637*file* – это либо строка, содержащая путь (абсолютный или относительный текущего рабочего каталога) к открываемому файлу, либо целочисленный файловый дескриптор оборачиваемого файла. (Если указан файловый дескриптор, он закрывается при закрытии возвращаемого объекта ввода-вывода, если только *closefd* не установлен в `False`.)3839*mode* – необязательная строка, определяющая режим, в котором открывается файл. По умолчанию `'r'`, что означает открытие для чтения в текстовом режиме. Другие распространённые значения: `'w'` для записи (с усечением файла, если он yже существует) и `'a'` для добавления (что на *некоторых* системах Unix означает, что *все* записи добавляются в конец файла независимо от текущей позиции). В текстовом режиме, если *encoding* не указан, используется кодировка, зависящая от платформы. (Для чтения и записи сырых байтов используйте двоичный режим и оставьте *encoding* неуказанным.) Доступные режимы:4041| Символ | Значение |42| --- | --- |43| `'r'` | открытие для чтения (по умолчанию) |44| `'w'` | открытие для записи, с предварительным усечением файла |45| `'a'` | открытие для записи, дозапись в конец файла, если он существует |46| `'b'` | двоичный режим |47| `'t'` | текстовый режим (по умолчанию) |48| `'+'` | открывает дисковый файл для обновления (чтения и записи) |49| `'U'` | режим универсальных новых строк (для обратной совместимости; не должен использоваться в новом коде) |5051Режим по умолчанию – `'rt'` (открыт для чтения текста). Для двоичного произвольного доступа режим `'w+b'` открывает и усекает файл до 0 байт, а `'r+b'` открывает файл без усечения.5253Python различает файлы, открытые в двоичном и текстовом режимах, даже если базовая операционная система этого не делает. Файлы, открытые в двоичном режиме (включая `'b'` в аргументе *mode*), возвращают содержимое в виде объектов `bytes` без какого-либо декодирования. В текстовом режиме (по умолчанию или когда `'t'` включён в аргумент *mode*) содержимое файла возвращается в виде строк [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode), при этом байты сначала декодируются с использованием кодировки, зависящей от платформы, или указанной *encoding*, если она задана.5455*buffering* – необязательное целое число, используемое для настройки политики буферизации. Передайте 0, чтобы отключить буферизацию (допустимо только в двоичном режиме), 1 – для построчной буферизации (только в текстовом режиме) и целое число \> 1 для указания размера буфера фиксированного размера. Если аргумент *buffering* не указан, политика буферизации по умолчанию работает следующим образом:5657- Двоичные файлы буферизуются блоками фиксированного размера; размер буфера выбирается эвристически, пытаясь определить «размер блока» базового устройства, и при неудаче использует [`DEFAULT_BUFFER_SIZE`](https://python-all.ru/2.7/library/io.html#io.DEFAULT_BUFFER_SIZE). Во многих системах буфер обычно имеет размер 4096 или 8192 байта.58- «Интерактивные» текстовые файлы (файлы, для которых `isatty()` возвращает True) используют построчную буферизацию. Остальные текстовые файлы используют политику, описанную выше для двоичных файлов.5960*encoding* – имя кодировки, используемой для декодирования или кодирования файла. Этот параметр следует использовать только в текстовом режиме. Кодировка по умолчанию зависит от платформы (возвращаемое значение [`locale.getpreferredencoding()`](https://python-all.ru/2.7/library/locale.html#locale.getpreferredencoding)), но можно использовать любую кодировку, поддерживаемую Python. Список поддерживаемых кодировок см. в модуле [`codecs`](https://python-all.ru/2.7/library/codecs.html#module-codecs).6162*errors* – необязательная строка, определяющая, как обрабатывать ошибки кодирования и декодирования; этот параметр нельзя использовать в двоичном режиме. Передайте `'strict'`, чтобы возбуждать исключение [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError) при ошибке кодирования (значение по умолчанию `None` даёт тот же эффект), или `'ignore'` для игнорирования ошибок. (Обратите внимание, что игнорирование ошибок кодирования может привести к потере данных.) `'replace'` приводит к вставке заменяющего маркера (например, `'?'`) в местах с некорректными данными. При записи можно использовать `'xmlcharrefreplace'` (замена на соответствующую символьную ссылку XML) или `'backslashreplace'` (замена на escape-последовательности с обратными слешами). Любое другое имя обработчика ошибок, зарегистрированное в [`codecs.register_error()`](https://python-all.ru/2.7/library/codecs.html#codecs.register_error), также допустимо.6364*newline* управляет работой [универсальных разделителей строк](https://python-all.ru/2.7/glossary.html#term-universal-newlines) (применяется только к текстовому режиму). Оно может быть `None`, `''`, `'\n'`, `'\r'` и `'\r\n'`. Работает следующим образом:6566- При вводе, если *newline* равен `None`, включается режим универсальных разделителей строк. Строки во входных данных могут заканчиваться на `'\n'`, `'\r'` или `'\r\n'`, и эти окончания преобразуются в `'\n'` перед возвратом вызывающему коду. Если оно равно `''`, режим универсальных разделителей строк включён, но окончания строк возвращаются вызывающему коду без преобразования. Если оно имеет любое другое допустимое значение, входные строки завершаются только указанной строкой, и окончание строки возвращается вызывающему коду без преобразования.67- При выводе, если *newline* равен `None`, все записанные символы `'\n'` переводятся в системный разделитель строк по умолчанию, [`os.linesep`](https://python-all.ru/2.7/library/os.html#os.linesep). Если *newline* равен `''`, преобразование не выполняется. Если *newline* имеет любое другое допустимое значение, все записанные символы `'\n'` преобразуются в указанную строку.6869Если *closefd* равен `False` и был указан файловый дескриптор, а не имя файла, базовый файловый дескриптор останется открытым при закрытии файла. Если указано имя файла, *closefd* не действует и должен быть `True` (по умолчанию).7071Тип файлового объекта, возвращаемого функцией [`open()`](https://python-all.ru/2.7/library/io.html#io.open), зависит от режима. Когда [`open()`](https://python-all.ru/2.7/library/io.html#io.open) используется для открытия файла в текстовом режиме (`'w'`, `'r'`, `'wt'`, `'rt'` и т.д.), возвращается подкласс [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase) (а именно [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper)). При открытии файла в двоичном режиме с буферизацией возвращается подкласс [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase). Конкретный класс различается: в двоичном режиме чтения возвращается [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader); в двоичном режиме записи и добавления возвращается [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter), а в режиме чтения/записи – [`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom). Когда буферизация отключена, возвращается сырой поток, подкласс [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), [`FileIO`](https://python-all.ru/2.7/library/io.html#io.FileIO).7273Также можно использовать строку [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode) или `bytes` в качестве файла как для чтения, так и для записи. Для строк [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode) [`StringIO`](https://python-all.ru/2.7/library/io.html#io.StringIO) может использоваться как файл, открытый в текстовом режиме, а для `bytes` [`BytesIO`](https://python-all.ru/2.7/library/io.html#io.BytesIO) может использоваться как файл, открытый в двоичном режиме.7475#### `exception io.BlockingIOError`7677Ошибка, возбуждаемая, когда блокировка может произойти на неблокирующем потоке. Наследует [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).7879В дополнение к атрибутам [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError), [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError) имеет один атрибут:8081#### `characters_written`8283Целое число, содержащее количество символов, записанных в поток до его блокировки.8485#### `exception io.UnsupportedOperation`8687Исключение, наследующее [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError) и [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError), которое вызывается, когда неподдерживаемая операция вызывается для потока.8889## 15.2.2. Базовые классы ввода-вывода9091#### `class io.IOBase`9293Абстрактный базовый класс для всех классов ввода-вывода, работающий с потоками байтов. Отсутствует открытый конструктор.9495Этот класс предоставляет пустые абстрактные реализации для многих методов, которые производные классы могут выборочно переопределять; реализации по умолчанию представляют файл, который нельзя читать, записывать или позиционировать.9697Хотя [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase) не объявляет `read()`, `readinto()`, или `write()`, поскольку их сигнатуры различаются, реализации и клиенты должны считать эти методы частью интерфейса. Кроме того, реализации могут возбуждать исключение [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError) при вызове операций, которые они не поддерживают.9899Базовым типом для двоичных данных, читаемых из файла или записываемых в него, является `bytes` (также известный как [`str`](https://python-all.ru/2.7/library/functions.html#str)). Аргументы методов также могут быть [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray) или [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview) массивов байтов. В некоторых случаях, таких как [`readinto()`](https://python-all.ru/2.7/library/io.html#io.RawIOBase.readinto), требуется записываемый объект, например [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray). Классы текстового ввода-вывода работают с данными [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode).100101Изменено в версии 2.7: Реализации должны поддерживать аргументы [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview).102103Обратите внимание, что вызов любого метода (даже запросов) для закрытого потока является неопределённым. В этом случае реализации могут возбудить [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).104105IOBase (и его подклассы) поддерживают протокол итератора, то есть объект [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase) можно перебирать, получая строки потока. Строки определяются немного по-разному в зависимости от того, является ли поток двоичным (возвращает `bytes`) или текстовым (возвращает строки [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode)). См. [`readline()`](https://python-all.ru/2.7/library/io.html#io.IOBase.readline) ниже.106107IOBase также является менеджером контекста и поэтому поддерживает оператор [`with`](https://python-all.ru/2.7/reference/compound_stmts.html#with). В этом примере *file* закрывается после завершения блока оператора [`with`](https://python-all.ru/2.7/reference/compound_stmts.html#with), даже если возникает исключение:108109```python110with io.open('spam.txt', 'w') as file:111 file.write(u'Spam and eggs!')112```113114[`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase) предоставляет следующие атрибуты данных и методы:115116#### `close()`117118Сбрасывает буферы и закрывает этот поток. Этот метод не оказывает эффекта, если файл уже закрыт. После закрытия файла любая операция с файлом (например, чтение или запись) возбудит [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError).119120Для удобства допускается вызывать этот метод несколько раз; однако эффект будет иметь только первый вызов.121122#### `closed`123124True, если поток закрыт.125126#### `fileno()`127128Возвращает базовый файловый дескриптор (целое число) потока, если он существует. Если объект ввода-вывода не использует файловый дескриптор, возбуждается [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).129130#### `flush()`131132Сбрасывает буферы записи потока, если это применимо. Для потоков только для чтения и неблокирующих потоков эта операция ничего не делает.133134#### `isatty()`135136Возвращает `True`, если поток данных является интерактивным (т.е. подключён к терминальному/tty-устройству).137138#### `readable()`139140Возвращает `True`, если из потока можно читать. Если `False`, `read()` вызовет [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).141142#### `readline(limit=-1)`143144Читает и возвращает одну строку из потока. Если указан *limit*, будет прочитано не более *limit* байт.145146Окончанием строки для бинарных файлов всегда является `b'\n'`; для текстовых файлов аргумент *newline* функции [`open()`](https://python-all.ru/2.7/library/io.html#io.open) позволяет выбрать распознаваемые окончания строк.147148#### `readlines(hint=-1)`149150Читает и возвращает список строк из потока. Можно указать *hint* для ограничения количества читаемых строк: чтение прекратится, когда общий размер (в байтах/символах) всех прочитанных строк превысит *hint*.151152Обратите внимание, что по файловым объектам уже можно итерироваться с помощью `for line in file: ...` без вызова `file.readlines()`.153154#### `seek(offset, whence=SEEK_SET)`155156Устанавливает позицию в потоке на заданное байтовое *offset*. *offset* интерпретируется относительно позиции, указанной в *whence*. Значение по умолчанию для *whence* – `SEEK_SET`. Допустимые значения для *whence*:157158- `SEEK_SET` или `0` – начало потока (по умолчанию); *offset* должно быть нулевым или положительным159- `SEEK_CUR` или `1` – текущая позиция в потоке; *offset* может быть отрицательным160- `SEEK_END` или `2` – конец потока; *offset* обычно отрицательный161162Возвращает новую абсолютную позицию.163164Новое в версии 2.7: константы `SEEK_*`165166#### `seekable()`167168Возвращает `True`, если поток поддерживает произвольный доступ. Если `False`, [`seek()`](https://python-all.ru/2.7/library/io.html#io.IOBase.seek), [`tell()`](https://python-all.ru/2.7/library/io.html#io.IOBase.tell) и [`truncate()`](https://python-all.ru/2.7/library/io.html#io.IOBase.truncate) вызовут исключение [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).169170#### `tell()`171172Возвращает текущую позицию в потоке.173174#### `truncate(size=None)`175176Изменяет размер потока до указанного *size* в байтах (или до текущей позиции, если *size* не указан). Текущая позиция в потоке не изменяется. Это изменение размера может увеличить или уменьшить текущий размер файла. В случае увеличения содержимое новой области файла зависит от платформы (в большинстве систем дополнительные байты заполняются нулями, в Windows они не определены). Возвращается новый размер файла.177178#### `writable()`179180Возвращает `True`, если поток поддерживает запись. Если `False`, `write()` и [`truncate()`](https://python-all.ru/2.7/library/io.html#io.IOBase.truncate) вызовут исключение [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError).181182#### `writelines(lines)`183184Записывает список строк в поток. Разделители строк не добавляются, поэтому обычно каждая переданная строка уже содержит разделитель в конце.185186#### `__del__()`187188Подготавливает объект к уничтожению. [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase) предоставляет реализацию этого метода по умолчанию, которая вызывает метод [`close()`](https://python-all.ru/2.7/library/io.html#io.IOBase.close) экземпляра.189190#### `class io.RawIOBase`191192Базовый класс для необработанного двоичного ввода-вывода. Он наследует [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase). Отсутствует открытый конструктор.193194Необработанный двоичный ввод-вывод обычно предоставляет низкоуровневый доступ к базовому устройству или API операционной системы и не пытается инкапсулировать его в высокоуровневые примитивы (это оставлено буферизованному и текстовому вводу-выводу, описанным далее на этой странице).195196Помимо атрибутов и методов из [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase), RawIOBase предоставляет следующие методы:197198#### `read(n=-1)`199200Читает до *n* байт из объекта и возвращает их. Для удобства, если *n* не указан или равен -1, вызывается [`readall()`](https://python-all.ru/2.7/library/io.html#io.RawIOBase.readall). В противном случае выполняется только один системный вызов. Может быть возвращено меньше *n* байт, если системный вызов возвращает меньше *n* байт.201202Если возвращено 0 байт, а *n* не равно 0, это означает конец файла. Если объект находится в неблокирующем режиме и нет доступных байтов, возвращается `None`.203204#### `readall()`205206Читает и возвращает все байты из потока до EOF, при необходимости выполняя несколько вызовов к потоку.207208#### `readinto(b)`209210Читает до len(b) байт в *b* и возвращает количество прочитанных байт. Объект *b* должен быть предварительно выделенным, доступным для записи массивом байт, либо [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray), либо [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview). Если объект находится в неблокирующем режиме и нет доступных байтов, возвращается `None`.211212#### `write(b)`213214Записывает *b* в нижележащий необработанный поток и возвращает количество записанных байт. Объект *b* должен быть массивом байт: либо `bytes`, [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray) или [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview). Возвращаемое значение может быть меньше `len(b)` в зависимости от особенностей нижележащего необработанного потока, и особенно если он находится в неблокирующем режиме. `None` возвращается, если необработанному потоку задано не блокироваться и ни один байт не может быть сразу записан в него. Вызывающий может освободить или изменить *b* после возврата из этого метода, поэтому реализация должна обращаться к *b* только во время вызова метода.215216#### `class io.BufferedIOBase`217218Базовый класс для двоичных потоков, поддерживающих тот или иной вид буферизации. Он наследует [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase). Отсутствует открытый конструктор.219220Основное отличие от [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase) заключается в том, что методы [`read()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.read), [`readinto()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.readinto) и [`write()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.write) будут пытаться (соответственно) прочитать столько входных данных, сколько запрошено, или потребить все переданные выходные данные, ценой, возможно, более одного системного вызова.221222Кроме того, эти методы могут вызывать [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError), если базовый небуферизованный поток находится в неблокирующем режиме и не может принять или отдать достаточно данных; в отличие от своих аналогов из [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), они никогда не вернут `None`.223224Кроме того, метод [`read()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.read) не имеет реализации по умолчанию, которая делегирует [`readinto()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.readinto).225226Типичная реализация [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) не должна наследовать от реализации [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), а должна оборачивать её, как это делают [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter) и [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader).227228[`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) предоставляет или переопределяет следующие методы и атрибут в дополнение к тем, что есть в [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase):229230#### `raw`231232Базовый сырой поток (экземпляр [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase)), с которым работает [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase). Это не является частью API [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) и может отсутствовать в некоторых реализациях.233234#### `detach()`235236Отделяет базовый сырой поток от буфера и возвращает его.237238После отсоединения сырого потока буфер переходит в нерабочее состояние.239240Некоторые буферы, такие как [`BytesIO`](https://python-all.ru/2.7/library/io.html#io.BytesIO), не имеют концепции одного сырого потока для возврата из этого метода. Они вызывают [`UnsupportedOperation`](https://python-all.ru/2.7/library/io.html#io.UnsupportedOperation).241242Новое в версии 2.7.243244#### `read(n=-1)`245246Читает и возвращает до *n* байт. Если аргумент опущен, равен `None` или отрицателен, данные читаются и возвращаются до достижения EOF. Пустой объект bytes возвращается, если поток уже находится в конце файла.247248Если аргумент положителен, а базовый сырой поток не является интерактивным, может быть выполнено несколько сырых чтений, чтобы обеспечить требуемое количество байт (если только не достигнут EOF). Но для интерактивных сырых потоков будет выполнено не более одного сырого чтения, и короткий результат не означает, что EOF неизбежен.249250Исключение [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError) возбуждается, если базовый сырой поток находится в неблокирующем режиме и в данный момент не содержит данных.251252#### `read1(n=-1)`253254Читает и возвращает до *n* байт, выполняя не более одного вызова метода [`read()`](https://python-all.ru/2.7/library/io.html#io.RawIOBase.read) нижележащего необработанного потока. Это может быть полезно при реализации собственной буферизации поверх объекта [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase).255256#### `readinto(b)`257258Читает до len(b) байт в *b* и возвращает количество прочитанных байт. Объект *b* должен быть предварительно выделенным, доступным для записи массивом байт, либо [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray), либо [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview).259260Как и [`read()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.read), может выполняться несколько чтений из нижележащего необработанного потока, если только последний не является «интерактивным».261262Исключение [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError) возбуждается, если базовый сырой поток находится в неблокирующем режиме и в данный момент не содержит данных.263264#### `write(b)`265266Записывает *b* и возвращает количество записанных байт (всегда равно `len(b)`, так как при неудачной записи будет возбуждено [`IOError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.IOError)). Объект *b* должен быть массивом байт: либо `bytes`, [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray) или [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview). В зависимости от реальной реализации эти байты могут быть сразу записаны в нижележащий поток или сохранены в буфере для повышения производительности и уменьшения задержек.267268В неблокирующем режиме возбуждается [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError), если данные необходимо записать в сырой поток, но он не может принять все данные без блокировки.269270Вызывающий код может освободить или изменить *b* после возврата из этого метода, поэтому реализация должна обращаться к *b* только во время вызова метода.271272## 15.2.3. Низкоуровневый файловый ввод-вывод273274#### `class io.FileIO(name, mode='r', closefd=True)`275276[`FileIO`](https://python-all.ru/2.7/library/io.html#io.FileIO) представляет собой файл на уровне операционной системы, содержащий данные в байтах. Он реализует интерфейс [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase) (а следовательно, и интерфейс [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase)).277278Параметр *name* может быть одним из двух:279280- строка, представляющая путь к открываемому файлу;281- целое число, представляющее номер существующего файлового дескриптора ОС, к которому результирующий объект [`FileIO`](https://python-all.ru/2.7/library/io.html#io.FileIO) предоставит доступ.282283Параметр *mode* может быть равен `'r'`, `'w'` или `'a'` для чтения (по умолчанию), записи или добавления. Файл будет создан, если он не существует при открытии на запись или добавление; он будет усечён при открытии на запись. Чтобы разрешить одновременное чтение и запись, добавьте `'+'` к режиму.284285Методы `read()` (при вызове с положительным аргументом), `readinto()` и `write()` этого класса будут выполнять только один системный вызов.286287Помимо атрибутов и методов из [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase) и [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), [`FileIO`](https://python-all.ru/2.7/library/io.html#io.FileIO) предоставляет следующие атрибуты и методы данных:288289#### `mode`290291Режим, указанный в конструкторе.292293#### `name`294295Имя файла. Это дескриптор файла, если имя не указано в конструкторе.296297## 15.2.4. Буферизированные потоки298299Буферизированные потоки ввода-вывода предоставляют интерфейс более высокого уровня к устройству ввода-вывода, чем небуферизированный.300301#### `class io.BytesIO([initial_bytes])`302303Реализация потока, использующая буфер байтов в памяти. Наследует [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase).304305Необязательный аргумент *initial\_bytes* – это объект `bytes`, содержащий начальные данные.306307[`BytesIO`](https://python-all.ru/2.7/library/io.html#io.BytesIO) предоставляет или переопределяет эти методы в дополнение к методам из [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) и [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase):308309#### `getvalue()`310311Возвращает `bytes`, содержащий всё содержимое буфера.312313#### `read1()`314315В [`BytesIO`](https://python-all.ru/2.7/library/io.html#io.BytesIO) это то же самое, что и `read()`.316317#### `class io.BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)`318319Буфер, предоставляющий доступ более высокого уровня к читаемому последовательному объекту [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase). Он наследует [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase). При чтении данных из этого объекта может быть запрошен больший объём данных из нижележащего необработанного потока, который сохраняется во внутреннем буфере. Затем буферизованные данные могут быть возвращены непосредственно при последующих чтениях.320321Конструктор создаёт [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader) для заданного читаемого потока *raw* и *buffer\_size*. Если *buffer\_size* не указан, используется [`DEFAULT_BUFFER_SIZE`](https://python-all.ru/2.7/library/io.html#io.DEFAULT_BUFFER_SIZE).322323[`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader) предоставляет или переопределяет следующие методы в дополнение к методам из [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) и [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase):324325#### `peek([n])`326327Возвращает байты из потока без продвижения позиции. Для выполнения вызова производится не более одного чтения из сырого потока. Количество возвращённых байт может быть меньше или больше запрошенного.328329#### `read([n])`330331Читает и возвращает *n* байт, или, если *n* не указан или отрицателен, до EOF или если вызов чтения заблокируется в неблокирующем режиме.332333#### `read1(n)`334335Читает и возвращает до *n* байт, выполняя только один вызов небуферизованного потока. Если в буфере есть хотя бы один байт, возвращаются только буферизованные байты. В противном случае выполняется один вызов чтения небуферизованного потока.336337#### `class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)`338339Буфер, предоставляющий доступ более высокого уровня к записываемому, последовательному объекту [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase). Наследует [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase). При записи в этот объект данные обычно помещаются во внутренний буфер. Буфер будет сбрасываться в нижележащий объект [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase) при различных условиях, включая:340341- когда буфер становится слишком мал для всех ожидающих данных;342- когда вызывается [`flush()`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter.flush);343- когда запрашивается `seek()` (для объектов [`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom));344- когда объект [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter) закрывается или уничтожается.345346Конструктор создает [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter) для заданного записываемого *сырого* потока. Если *buffer\_size* не указан, по умолчанию используется [`DEFAULT_BUFFER_SIZE`](https://python-all.ru/2.7/library/io.html#io.DEFAULT_BUFFER_SIZE).347348Третий аргумент, *max\_buffer\_size*, поддерживается, но не используется и устарел.349350[`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter) предоставляет или переопределяет следующие методы в дополнение к методам из [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) и [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase):351352#### `flush()`353354Принудительно передает байты, находящиеся в буфере, в сырой поток. Если сырой поток блокируется, должно быть возбуждено исключение [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError).355356#### `write(b)`357358Записывает *b* и возвращает количество записанных байт. Объект *b* должен быть массивом байт: либо `bytes`, [`bytearray`](https://python-all.ru/2.7/library/functions.html#bytearray) или [`memoryview`](https://python-all.ru/2.7/library/stdtypes.html#memoryview). В неблокирующем режиме возбуждается [`BlockingIOError`](https://python-all.ru/2.7/library/io.html#io.BlockingIOError), если буфер нужно сбросить, но необработанный поток блокируется.359360#### `class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)`361362Буферизированный интерфейс для потоков с произвольным доступом. Он наследует [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader) и [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter), а также поддерживает функционал `seek()` и `tell()`.363364Конструктор создает читатель и писатель для сырого потока с произвольным доступом, заданного в первом аргументе. Если *buffer\_size* опущен, по умолчанию используется [`DEFAULT_BUFFER_SIZE`](https://python-all.ru/2.7/library/io.html#io.DEFAULT_BUFFER_SIZE).365366Третий аргумент, *max\_buffer\_size*, поддерживается, но не используется и устарел.367368[`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom) способен на всё то же, что [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader) или [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter).369370#### `class io.BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE)`371372Буферизованный объект ввода-вывода, объединяющий два однонаправленных [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase) объекта (один для чтения, другой для записи) в единую двунаправленную конечную точку. Наследует [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase).373374*reader* и *writer* – это объекты [`RawIOBase`](https://python-all.ru/2.7/library/io.html#io.RawIOBase), которые являются читаемыми и записываемыми соответственно. Если *buffer\_size* опущен, по умолчанию используется [`DEFAULT_BUFFER_SIZE`](https://python-all.ru/2.7/library/io.html#io.DEFAULT_BUFFER_SIZE).375376Четвёртый аргумент, *max\_buffer\_size*, поддерживается, но не используется и устарел.377378[`BufferedRWPair`](https://python-all.ru/2.7/library/io.html#io.BufferedRWPair) реализует все методы [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase), кроме [`detach()`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase.detach), который вызывает [`UnsupportedOperation`](https://python-all.ru/2.7/library/io.html#io.UnsupportedOperation).379380> **Предупреждение**381>382> [`BufferedRWPair`](https://python-all.ru/2.7/library/io.html#io.BufferedRWPair) не пытается синхронизировать доступ к своим базовым сырым потокам. Не следует передавать ему один и тот же объект в качестве читателя и писателя; вместо этого используйте [`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom).383384## 15.2.5. Текстовый ввод-вывод385386#### `class io.TextIOBase`387388Базовый класс для текстовых потоков. Этот класс предоставляет интерфейс для ввода-вывода потока на основе символов Unicode и строк. Нет метода `readinto()`, поскольку строки [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode) в Python являются неизменяемыми. Наследует [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase). Открытого конструктора нет.389390[`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase) предоставляет или переопределяет следующие атрибуты данных и методы в дополнение к атрибутам и методам из [`IOBase`](https://python-all.ru/2.7/library/io.html#io.IOBase):391392#### `encoding`393394Имя кодировки, используемой для декодирования байтов потока в строки и для кодирования строк в байты.395396#### `errors`397398Настройка обработки ошибок декодера или кодера.399400#### `newlines`401402Строка, кортеж строк или `None`, указывающие, какие символы новой строки были преобразованы на данный момент. В зависимости от реализации и исходных флагов конструктора это может быть недоступно.403404#### `buffer`405406Базовый двоичный буфер (экземпляр [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase)), с которым работает [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase). Это не часть API [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase) и может отсутствовать в некоторых реализациях.407408#### `detach()`409410Отделяет базовый двоичный буфер от [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase) и возвращает его.411412После отсоединения базового буфера [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase) непригоден для использования.413414Некоторые реализации [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase), например [`StringIO`](https://python-all.ru/2.7/library/io.html#io.StringIO), могут не иметь понятия базового буфера, и вызов этого метода вызовет [`UnsupportedOperation`](https://python-all.ru/2.7/library/io.html#io.UnsupportedOperation).415416Новое в версии 2.7.417418#### `read(n=-1)`419420Читает и возвращает не более *n* символов из потока в виде одного [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode). Если *n* отрицательно или `None`, читает до конца файла.421422#### `readline(limit=-1)`423424Читает до символа новой строки или конца файла и возвращает одну строку `unicode`. Если поток уже находится в конце файла, возвращается пустая строка.425426Если *limit* указан, будет прочитано не более *limit* символов.427428#### `seek(offset, whence=SEEK_SET)`429430Изменяет позицию в потоке на заданное значение *offset*. Поведение зависит от параметра *whence*. Значением по умолчанию для *whence* является `SEEK_SET`.431432- `SEEK_SET` или `0`: поиск от начала потока (по умолчанию); *offset* должен быть либо числом, возвращённым [`TextIOBase.tell()`](https://python-all.ru/2.7/library/io.html#io.TextIOBase.tell), либо нулём. Любое другое значение *offset* приводит к неопределённому поведению.433- `SEEK_CUR` или `1`: «поиск» в текущую позицию; *offset* должен быть нулём, что является пустой операцией (все остальные значения не поддерживаются).434- `SEEK_END` или `2`: поиск в конец потока; *offset* должен быть нулём (все остальные значения не поддерживаются).435436Возвращает новую абсолютную позицию в виде непрозрачного числа.437438Новое в версии 2.7: Константы `SEEK_*`.439440#### `tell()`441442Возвращает текущую позицию в потоке в виде непрозрачного числа. Обычно это число не соответствует количеству байт в базовом двоичном хранилище.443444#### `write(s)`445446Записывает строку [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode) *s* в поток и возвращает количество записанных символов.447448#### `class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False)`449450Буферизованный текстовый поток поверх [`BufferedIOBase`](https://python-all.ru/2.7/library/io.html#io.BufferedIOBase) двоичного потока. Наследует [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase).451452Параметр *encoding* задаёт имя кодировки, в которой поток будет декодироваться или кодироваться. По умолчанию [`locale.getpreferredencoding()`](https://python-all.ru/2.7/library/locale.html#locale.getpreferredencoding).453454Параметр *errors* – необязательная строка, определяющая способ обработки ошибок кодирования и декодирования. Передайте `'strict'`, чтобы вызывать исключение [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError) при ошибке кодирования (по умолчанию `None` даёт тот же эффект), или `'ignore'`, чтобы игнорировать ошибки. (Обратите внимание, что игнорирование ошибок кодирования может привести к потере данных.) `'replace'` приводит к вставке замещающего маркера (например `'?'`) в место с некорректными данными. При записи можно использовать `'xmlcharrefreplace'` (замена соответствующей ссылкой на символ XML) или `'backslashreplace'` (замена escape-последовательностями с обратной косой чертой). Также доступно любое другое имя обработчика ошибок, зарегистрированное в [`codecs.register_error()`](https://python-all.ru/2.7/library/codecs.html#codecs.register_error).455456Параметр *newline* управляет обработкой концов строк. Он может принимать значения `None`, `''`, `'\n'`, `'\r'` и `'\r\n'`. Работает следующим образом:457458- При вводе, если параметр *newline* равен `None`, включается режим [универсальных символов новой строки](https://python-all.ru/2.7/glossary.html#term-universal-newlines). Строки во входных данных могут заканчиваться на `'\n'`, `'\r'` или `'\r\n'`, и они преобразуются в `'\n'` перед возвратом вызывающему. Если он равен `''`, режим универсальных символов новой строки включён, но окончания строк возвращаются вызывающему без преобразования. Если он имеет любое другое допустимое значение, входные строки завершаются только заданной строкой, и окончание строки возвращается вызывающему без преобразования.459- При выводе, если параметр *newline* равен `None`, все записываемые символы `'\n'` преобразуются в системный разделитель строк по умолчанию [`os.linesep`](https://python-all.ru/2.7/library/os.html#os.linesep). Если *newline* равен `''`, преобразование не выполняется. Если *newline* имеет любое другое допустимое значение, все записываемые символы `'\n'` преобразуются в заданную строку.460461Если *line\_buffering* равен `True`, то `flush()` подразумевается, когда вызов write содержит символ новой строки или возврата каретки.462463[`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper) предоставляет один атрибут в дополнение к атрибутам [`TextIOBase`](https://python-all.ru/2.7/library/io.html#io.TextIOBase) и его родительских классов:464465#### `line_buffering`466467Определяет, включена ли построчная буферизация.468469#### `class io.StringIO(initial_value=u'', newline=u'\n')`470471Поток в памяти для текста Unicode. Наследует [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper).472473Начальное значение буфера можно задать, передав *initial\_value*. Если включена трансляция символов новой строки, они будут кодироваться так, как если бы через [`write()`](https://python-all.ru/2.7/library/io.html#io.TextIOBase.write). Поток данных позиционируется в начало буфера.474475Аргумент *newline* работает так же, как в [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper). По умолчанию только символ `\n` считается концом строки, и никакого преобразования символов новой строки не выполняется. Если *newline* установлен в `None`, символы новой строки записываются как `\n` на всех платформах, но при чтении по-прежнему выполняется декодирование универсальных символов новой строки.476477[`StringIO`](https://python-all.ru/2.7/library/io.html#io.StringIO) предоставляет этот метод в дополнение к методам из [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper) и его родительских классов:478479#### `getvalue()`480481Возвращает `unicode`, содержащий всё содержимое буфера в любой момент до вызова метода `close()` объекта [`StringIO`](https://python-all.ru/2.7/library/io.html#io.StringIO). Символы новой строки декодируются как при [`read()`](https://python-all.ru/2.7/library/io.html#io.TextIOBase.read), хотя позиция потока не изменяется.482483Пример использования:484485```python486import io487488output = io.StringIO()489output.write(u'First line.\n')490output.write(u'Second line.\n')491492# Извлечь содержимое файла – это будет493# u'Первая строка.\nВторая строка.\n'494contents = output.getvalue()495496# Закрыть объект и освободить буфер памяти –497# .getvalue() теперь будет вызывать исключение.498output.close()499```500501#### `class io.IncrementalNewlineDecoder`502503Вспомогательный кодек для декодирования символов новой строки в режиме [универсальных новых строк](https://python-all.ru/2.7/glossary.html#term-universal-newlines). Наследует [`codecs.IncrementalDecoder`](https://python-all.ru/2.7/library/codecs.html#codecs.IncrementalDecoder).504505## 15.2.6. Расширенные темы506507Здесь будут рассмотрены несколько дополнительных тем, относящихся к конкретным реализациям ввода-вывода, описанным выше.508509### 15.2.6.1. Производительность510511#### 15.2.6.1.1. Двоичный ввод-вывод512513Читая и записывая только большие блоки данных, даже когда пользователь запрашивает один байт, буферизованный ввод-вывод скрывает любую неэффективность вызова и выполнения небуферизованных процедур ввода-вывода операционной системы. Выигрыш сильно зависит от ОС и типа выполняемого ввода-вывода (например, в некоторых современных ОС, таких как Linux, небуферизованный дисковый ввод-вывод может быть таким же быстрым, как буферизованный). Однако суть в том, что буферизованный ввод-вывод обеспечивает предсказуемую производительность независимо от платформы и нижележащего устройства. Поэтому почти всегда предпочтительнее использовать буферизованный ввод-вывод, а не небуферизованный.514515#### 15.2.6.1.2. Текстовый ввод-вывод516517Текстовый ввод-вывод через двоичное хранилище (например, файл) значительно медленнее двоичного ввода-вывода через то же хранилище, поскольку он подразумевает преобразование из Unicode в двоичные данные с использованием кодека символов. Это может стать заметным при обработке больших объёмов текстовых данных (например, очень больших файлов журналов). Кроме того, `TextIOWrapper.tell()` и `TextIOWrapper.seek()` оба довольно медленны из-за используемого алгоритма восстановления.518519[`StringIO`](https://python-all.ru/2.7/library/io.html#io.StringIO), однако, является встроенным контейнером юникода в памяти и будет демонстрировать скорость, аналогичную [`BytesIO`](https://python-all.ru/2.7/library/io.html#io.BytesIO).520521### 15.2.6.2. Многопоточность522523Объекты [`FileIO`](https://python-all.ru/2.7/library/io.html#io.FileIO) являются потокобезопасными в той степени, в какой потокобезопасны системные вызовы (например, `read(2)` в Unix), которые они оборачивают.524525Двоичные буферизованные объекты (экземпляры [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader), [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter), [`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom) и [`BufferedRWPair`](https://python-all.ru/2.7/library/io.html#io.BufferedRWPair)) защищают свои внутренние структуры с помощью блокировки; поэтому их можно безопасно вызывать из нескольких потоков одновременно.526527Объекты [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper) не являются потокобезопасными.528529### 15.2.6.3. Реентерабельность530531Двоичные буферизованные объекты (экземпляры [`BufferedReader`](https://python-all.ru/2.7/library/io.html#io.BufferedReader), [`BufferedWriter`](https://python-all.ru/2.7/library/io.html#io.BufferedWriter), [`BufferedRandom`](https://python-all.ru/2.7/library/io.html#io.BufferedRandom) и [`BufferedRWPair`](https://python-all.ru/2.7/library/io.html#io.BufferedRWPair)) не являются реентерабельными. Хотя в обычных ситуациях повторные вызовы не происходят, они могут возникнуть при выполнении ввода-вывода в обработчике [`signal`](https://python-all.ru/2.7/library/signal.html#module-signal). Если предпринимается попытка повторного входа в буферизованный объект, когда к нему уже есть доступ *из того же потока*, то возбуждается исключение [`RuntimeError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.RuntimeError).532533Вышесказанное неявно распространяется и на текстовые файлы, поскольку функция [`open()`](https://python-all.ru/2.7/library/functions.html#open) помещает буферизованный объект внутрь [`TextIOWrapper`](https://python-all.ru/2.7/library/io.html#io.TextIOWrapper). Это включает стандартные потоки и, следовательно, также затрагивает встроенную функцию [`print()`](https://python-all.ru/2.7/library/functions.html#print).534