Документация Python неофициальный перевод

inputoutput.md

401 строк · 33.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3/tutorial/inputoutput.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 7. Ввод и вывод89Есть несколько способов отображения вывода программы: данные можно выводить в удобочитаемой форме или записывать в файл для последующего использования. В этой главе рассматриваются некоторые из возможностей.1011## 7.1. Более изощрённое форматирование вывода1213До сих пор мы встречали два способа записи значений: *инструкции-выражения* и функция [`print()`](https://python-all.ru/3/library/functions.html#print). (Третий способ – использовать метод [`write()`](https://python-all.ru/3/library/io.html#io.TextIOBase.write) файловых объектов; стандартный файл вывода можно указать как `sys.stdout`. Подробнее об этом см. в Справочнике по библиотеке.)1415Часто требуется более точный контроль форматирования вывода, чем просто вывод значений, разделённых пробелами. Существует несколько способов форматирования вывода.1617- Чтобы использовать [f-строки](https://python-all.ru/3/tutorial/inputoutput.html#tut-f-strings), начните строку с `f` или `F` перед открывающей кавычкой или тройной кавычкой. Внутри этой строки можно записать выражение Python между символами `{` и `}`, которые могут ссылаться на переменные или литеральные значения.1819  ```python20  >>> year = 201621  >>> event = 'Referendum'22  >>> f'Results of the {year} {event}'23  'Results of the 2016 Referendum'24  ```25- Метод строки [`str.format()`](https://python-all.ru/3/library/stdtypes.html#str.format) требует больше ручного труда. По-прежнему используются `{` и `}`, чтобы отметить место подстановки переменной, и можно указать подробные директивы форматирования, но также нужно предоставить форматируемые данные. В следующем блоке кода приведены два примера форматирования переменных:2627  ```python28  >>> yes_votes = 42_572_65429  >>> total_votes = 85_705_14930  >>> percentage = yes_votes / total_votes31  >>> '{:-9} YES votes  {:2.2%}'.format(yes_votes, percentage)32  ' 42572654 YES votes  49.67%'33  ```3435  Обратите внимание, как `yes_votes` дополняются пробелами, а знак минуса ставится только для отрицательных чисел. В примере также выводится `percentage`, умноженное на 100, с двумя знаками после запятой и с символом процента (подробнее см. [Мини-язык спецификации формата](https://python-all.ru/3/library/string.html#formatspec)).36- Наконец, можно выполнять всю обработку строк самостоятельно, используя операции взятия среза и конкатенации, чтобы создать любой макет. Тип строка имеет несколько методов, которые выполняют полезные операции по дополнению строк до заданной ширины столбца.3738Если не требуется изощрённый вывод, а нужно лишь быстро отобразить некоторые переменные для отладки, любое значение можно преобразовать в строку с помощью функций [`repr()`](https://python-all.ru/3/library/functions.html#repr) или [`str()`](https://python-all.ru/3/library/stdtypes.html#str).3940Функция [`str()`](https://python-all.ru/3/library/stdtypes.html#str) предназначена для возврата представлений значений, которые достаточно удобочитаемы, тогда как [`repr()`](https://python-all.ru/3/library/functions.html#repr) предназначена для создания представлений, которые могут быть прочитаны интерпретатором (или вызовет [`SyntaxError`](https://python-all.ru/3/library/exceptions.html#SyntaxError), если нет эквивалентного синтаксиса). Для объектов, не имеющих специального представления для человека, `str()` вернёт то же значение, что и `repr()`. Многие значения, такие как числа или структуры вроде списков и словарей, имеют одинаковое представление при использовании любой функции. Строки, в частности, имеют два различных представления.4142Несколько примеров:4344```python45>>> s = 'Hello, world.'46>>> str(s)47'Hello, world.'48>>> repr(s)49"'Hello, world.'"50>>> str(1/7)51'0.14285714285714285'52>>> x = 10 * 3.2553>>> y = 200 * 20054>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'55>>> print(s)56The value of x is 32.5, and y is 40000...57>>> # repr() строки добавляет кавычки и обратную косую черту:58>>> hello = 'hello, world\n'59>>> hellos = repr(hello)60>>> print(hellos)61'hello, world\n'62>>> # Аргументом repr() может быть любой объект Python:63>>> repr((x, y, ('spam', 'eggs')))64"(32.5, 40000, ('spam', 'eggs'))"65```6667Модуль [`string`](https://python-all.ru/3/library/string.html#module-string) поддерживает простой подход к шаблонизации на основе регулярных выражений через [`string.Template`](https://python-all.ru/3/library/string.html#string.Template). Это даёт ещё один способ подстановки значений в строки, используя заполнители вида `$x` и заменяя их значениями из словаря. Этот синтаксис прост в использовании, хотя предоставляет гораздо меньше возможностей для форматирования.6869### 7.1.1. Форматированные строковые литералы7071[Форматированные строковые литералы](https://python-all.ru/3/reference/lexical_analysis.html#f-strings) (также называемые f-строками) позволяют включать значение выражений Python внутрь строки, добавляя префикс `f` или `F` и записывая выражения в виде `{expression}`.7273За выражением может следовать необязательный спецификатор формата. Это обеспечивает более точный контроль над форматированием значения. В следующем примере число π округляется до трёх знаков после запятой:7475```python76>>> import math77>>> print(f'The value of pi is approximately {math.pi:.3f}.')78The value of pi is approximately 3.142.79```8081Передача целого числа после `':'` устанавливает минимальную ширину поля в символах. Это полезно для выравнивания столбцов.8283```python84>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}85>>> for name, phone in table.items():86...     print(f'{name:10} ==> {phone:10d}')87...88Sjoerd     ==>       412789Jack       ==>       409890Dcab       ==>       767891```9293Другие модификаторы можно использовать для преобразования значения перед форматированием. `'!a'` применяет [`ascii()`](https://python-all.ru/3/library/functions.html#ascii), `'!s'` применяет [`str()`](https://python-all.ru/3/library/stdtypes.html#str), а `'!r'` применяет [`repr()`](https://python-all.ru/3/library/functions.html#repr):9495```python96>>> animals = 'eels'97>>> print(f'My hovercraft is full of {animals}.')98My hovercraft is full of eels.99>>> print(f'My hovercraft is full of {animals!r}.')100My hovercraft is full of 'eels'.101```102103Спецификатор `=` можно использовать для развёртывания выражения в текст выражения, знак равенства, а затем представление вычисленного выражения:104105```python106>>> bugs = 'roaches'107>>> count = 13108>>> area = 'living room'109>>> print(f'Debugging {bugs=} {count=} {area=}')110Debugging bugs='roaches' count=13 area='living room'111```112113См. [самодокументируемые выражения](https://python-all.ru/3/whatsnew/3.8.html#bpo-36817-whatsnew) для получения дополнительной информации о спецификаторе `=`. Справочные сведения об этих спецификациях формата см. в руководстве по [Мини-языку спецификации формата](https://python-all.ru/3/library/string.html#formatspec).114115### 7.1.2. Метод format() строк116117Базовое использование метода [`str.format()`](https://python-all.ru/3/library/stdtypes.html#str.format) выглядит так:118119```python120>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))121We are the knights who say "Ni!"122```123124Скобки и символы внутри них (называемые полями формата) заменяются на объекты, переданные методу [`str.format()`](https://python-all.ru/3/library/stdtypes.html#str.format). Число в скобках можно использовать для указания позиции объекта, переданного методу `str.format()`.125126```python127>>> print('{0} and {1}'.format('spam', 'eggs'))128spam and eggs129>>> print('{1} and {0}'.format('spam', 'eggs'))130eggs and spam131```132133Если в методе [`str.format()`](https://python-all.ru/3/library/stdtypes.html#str.format) используются именованные аргументы, на их значения ссылаются по имени аргумента.134135```python136>>> print('This {food} is {adjective}.'.format(137...       food='spam', adjective='absolutely horrible'))138This spam is absolutely horrible.139```140141Позиционные и именованные аргументы можно произвольно комбинировать:142143```python144>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',145...                                                    other='Georg'))146The story of Bill, Manfred, and Georg.147```148149Если имеется очень длинная строка формата, которую не хочется разбивать, было бы удобно ссылаться на форматируемые переменные по имени, а не по позиции. Это можно сделать, просто передав словарь и используя квадратные скобки `'[]'` для доступа к ключам.150151```python152>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}153>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '154...       'Dcab: {0[Dcab]:d}'.format(table))155Jack: 4098; Sjoerd: 4127; Dcab: 8637678156```157158Это можно сделать также, передав словарь `table` в качестве именованных аргументов с помощью нотации `**` .159160```python161>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}162>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))163Jack: 4098; Sjoerd: 4127; Dcab: 8637678164```165166Это особенно удобно в сочетании со встроенной функцией [`vars()`](https://python-all.ru/3/library/functions.html#vars), которая возвращает словарь, содержащий все локальные переменные:167168```python169>>> table = {k: str(v) for k, v in vars().items()}170>>> message = " ".join([f'{k}: ' + '{' + k +'};' for k in table.keys()])171>>> print(message.format(**table))172__name__: __main__; __doc__: None; __package__: None; __loader__: ...173```174175Например, следующие строки создают аккуратно выровненный набор столбцов, показывающих целые числа, их квадраты и кубы:176177```python178>>> for x in range(1, 11):179...     print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))180...181 1   1    1182 2   4    8183 3   9   27184 4  16   64185 5  25  125186 6  36  216187 7  49  343188 8  64  512189 9  81  72919010 100 1000191```192193Полный обзор форматирования строк с помощью [`str.format()`](https://python-all.ru/3/library/stdtypes.html#str.format) см. в [Синтаксис строк формата](https://python-all.ru/3/library/string.html#formatstrings).194195### 7.1.3. Ручное форматирование строк196197Вот та же таблица квадратов и кубов, отформатированная вручную:198199```python200>>> for x in range(1, 11):201...     print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')202...     # Обратите внимание на использование 'end' в предыдущей строке203...     print(repr(x*x*x).rjust(4))204...205 1   1    1206 2   4    8207 3   9   27208 4  16   64209 5  25  125210 6  36  216211 7  49  343212 8  64  512213 9  81  72921410 100 1000215```216217(Обратите внимание, что один пробел между столбцами добавляется тем, как работает [`print()`](https://python-all.ru/3/library/functions.html#print): он всегда вставляет пробелы между своими аргументами.)218219Метод [`str.rjust()`](https://python-all.ru/3/library/stdtypes.html#str.rjust) строковых объектов выравнивает строку по правому краю в поле заданной ширины, дополняя её пробелами слева. Существуют подобные методы [`str.ljust()`](https://python-all.ru/3/library/stdtypes.html#str.ljust) и [`str.center()`](https://python-all.ru/3/library/stdtypes.html#str.center). Эти методы ничего не выводят, они просто возвращают новую строку. Если входная строка слишком длинная, они не обрезают её, а возвращают без изменений; это нарушит выравнивание столбцов, но обычно это лучше, чем альтернатива, которая состоит в искажении значения. (Если действительно нужно обрезать, всегда можно добавить операцию среза, как в `x.ljust(n)[:n]`.)220221Существует ещё один метод, [`str.zfill()`](https://python-all.ru/3/library/stdtypes.html#str.zfill), который дополняет числовую строку слева нулями. Он учитывает знаки плюс и минус:222223```python224>>> '12'.zfill(5)225'00012'226>>> '-3.14'.zfill(7)227'-003.14'228>>> '3.14159265359'.zfill(5)229'3.14159265359'230```231232### 7.1.4. Старое форматирование строк233234Оператор % (остаток от деления) также можно использовать для форматирования строк. Если задана строка `format % values` (где *format* – строка), спецификации преобразования `%` в *format* заменяются нулём или более элементами из *values*. Эта операция широко известна как строковая интерполяция. Например:235236```python237>>> import math238>>> print('The value of pi is approximately %5.3f.' % math.pi)239The value of pi is approximately 3.142.240```241242Дополнительную информацию можно найти в разделе [Форматирование строк в стиле printf](https://python-all.ru/3/library/stdtypes.html#old-string-formatting).243244## 7.2. Чтение и запись файлов245246[`open()`](https://python-all.ru/3/library/functions.html#open) возвращает [файловый объект](https://python-all.ru/3/glossary.html#term-file-object) и чаще всего используется с двумя позиционными аргументами и одним именованным аргументом: `open(filename, mode, encoding=None)`247248```python249>>> f = open('workfile', 'w', encoding="utf-8")250```251252Первый аргумент – строка, содержащая имя файла. Второй аргумент – ещё одна строка, содержащая несколько символов, описывающих способ использования файла. *mode* может быть `'r'` для чтения, `'w'` только для записи (существующий файл с таким же именем будет стёрт), а `'a'` открывает файл для дополнения; любые записанные данные автоматически добавляются в конец. `'r+'` открывает файл и для чтения, и для записи. Аргумент *mode* необязателен; если он опущен, предполагается `'r'`.253254Обычно файлы открываются в *текстовом режиме*, то есть вы читаете и записываете строки в файл и из файла, которые кодируются в определённой *кодировке*. Если *encoding* не указана, используется значение по умолчанию, зависящее от платформы (см. [`open()`](https://python-all.ru/3/library/functions.html#open)). Поскольку UTF-8 – современный де-факто стандарт, рекомендуется `encoding="utf-8"` если только вы не знаете, что вам нужна другая кодировка. Добавление `'b'` к режиму открывает файл в *двоичном режиме*. Данные в двоичном режиме читаются и записываются как объекты [`bytes`](https://python-all.ru/3/library/stdtypes.html#bytes). Нельзя указывать *encoding* при открытии файла в двоичном режиме.255256В текстовом режиме при чтении по умолчанию концевые символы строки, зависящие от платформы (`\n` в Unix, `\r\n` в Windows), преобразуются в простой `\n`. При записи в текстовом режиме по умолчанию вхождения `\n` преобразуются обратно в концевые символы, зависящие от платформы. Эта фоновая модификация данных файла нормальна для текстовых файлов, но повредит двоичные данные, например, в файлах `JPEG` или `EXE`. Будьте очень осторожны и используйте двоичный режим при чтении и записи таких файлов.257258Рекомендуется использовать ключевое слово [`with`](https://python-all.ru/3/reference/compound_stmts.html#with) при работе с файловыми объектами. Преимущество в том, что файл корректно закрывается после завершения своего блока, даже если в какой-то момент возникло исключение. Использование `with` также намного короче, чем написание эквивалентных блоков [`try`](https://python-all.ru/3/reference/compound_stmts.html#try)-[`finally`](https://python-all.ru/3/reference/compound_stmts.html#finally):259260```python261>>> with open('workfile', encoding="utf-8") as f:262...     read_data = f.read()263264>>> # Можно проверить, что файл автоматически закрыт.265>>> f.closed266True267```268269Если вы не используете ключевое слово [`with`](https://python-all.ru/3/reference/compound_stmts.html#with), то следует вызвать `f.close()`, чтобы закрыть файл и немедленно освободить все системные ресурсы, используемые им.270271> **Предупреждение**272>273> Вызов `f.write()` без использования ключевого слова `with` или вызов `f.close()` **может** привести к тому, что аргументы `f.write()` не будут полностью записаны на диск, даже если программа завершится успешно.274275После закрытия файлового объекта – с помощью инструкции [`with`](https://python-all.ru/3/reference/compound_stmts.html#with) или вызова `f.close()` – попытки использовать файловый объект автоматически завершатся неудачей.276277```python278>>> f.close()279>>> f.read()280Traceback (most recent call last):281  File "<stdin>", line 1, in <module>282ValueError: I/O operation on closed file.283```284285### 7.2.1. Методы файловых объектов286287Остальные примеры в этом разделе предполагают, что файловый объект с именем `f` уже создан.288289Чтобы прочитать содержимое файла, вызовите `f.read(size)`, который читает некоторое количество данных и возвращает их в виде строки (в текстовом режиме) или объекта bytes (в двоичном режиме). *size* – необязательный числовой аргумент. Если *size* опущен или отрицателен, будет прочитано и возвращено всё содержимое файла; это ваша проблема, если файл вдвое больше памяти вашего компьютера. В противном случае будет прочитано и возвращено не более *size* символов (в текстовом режиме) или *size* байтов (в двоичном режиме). Если достигнут конец файла, `f.read()` вернёт пустую строку (`''`).290291```python292>>> f.read()293'This is the entire file.\n'294>>> f.read()295''296```297298`f.readline()` читает одну строку из файла; символ новой строки (`\n`) остаётся в конце строки и опускается только в последней строке файла, если файл не заканчивается переводом строки. Это делает возвращаемое значение однозначным: если `f.readline()` возвращает пустую строку, конец файла достигнут, тогда как пустая строка представляется как `'\n'`, строка, содержащая только один символ новой строки.299300```python301>>> f.readline()302'This is the first line of the file.\n'303>>> f.readline()304'Second line of the file\n'305>>> f.readline()306''307```308309Для чтения строк из файла можно выполнять итерацию по файловому объекту. Это эффективно по памяти, быстро и приводит к простому коду:310311```python312>>> for line in f:313...     print(line, end='')314...315This is the first line of the file.316Second line of the file317```318319Если нужно прочитать все строки файла в виде списка, можно также использовать `list(f)` или `f.readlines()`.320321`f.write(string)` записывает содержимое *string* в файл и возвращает количество записанных символов.322323```python324>>> f.write('This is a test\n')32515326```327328Объекты других типов необходимо преобразовать – либо в строку (в текстовом режиме), либо в объект bytes (в двоичном режиме) – перед записью:329330```python331>>> value = ('the answer', 42)332>>> s = str(value)  # преобразовать кортеж в строку333>>> f.write(s)33418335```336337`f.tell()` возвращает целое число, указывающее текущую позицию в файле для данного файлового объекта, представленную как количество байтов от начала файла в двоичном режиме и непрозрачное число в текстовом режиме.338339Чтобы изменить позицию файлового объекта, используйте `f.seek(offset, whence)`. Позиция вычисляется как добавление *offset* к опорной точке; опорная точка выбирается аргументом *whence*. Значение *whence* равное 0 отсчитывает от начала файла, 1 использует текущую позицию файла, а 2 использует конец файла в качестве опорной точки. *whence* можно опустить, и по умолчанию оно равно 0, что соответствует началу файла.340341```python342>>> f = open('workfile', 'rb+')343>>> f.write(b'0123456789abcdef')34416345>>> f.seek(5)      # Перейти к 6-му байту в файле3465347>>> f.read(1)348b'5'349>>> f.seek(-3, 2)  # Перейти к 3-му байту от конца35013351>>> f.read(1)352b'd'353```354355В текстовых файлах (открытых без `b` в строке режима) разрешены только позиционирования относительно начала файла (исключение – позиционирование в самый конец файла с помощью `seek(0, 2)`), и единственные допустимые значения *offset* – это те, что возвращены `f.tell()`, или ноль. Любое другое значение *offset* приводит к неопределённому поведению.356357Файловые объекты имеют некоторые дополнительные методы, такие как [`isatty()`](https://python-all.ru/3/library/io.html#io.IOBase.isatty) и [`truncate()`](https://python-all.ru/3/library/io.html#io.IOBase.truncate), которые используются реже; обратитесь к Справочнику библиотеки для получения полного руководства по файловым объектам.358359### 7.2.2. Сохранение структурированных данных с помощью [`json`](https://python-all.ru/3/library/json.html#module-json)360361Строки можно легко записать в файл и прочитать из файла. С числами немного сложнее, поскольку метод [`read()`](https://python-all.ru/3/library/io.html#io.TextIOBase.read) возвращает только строки, которые затем нужно передать такой функции, как [`int()`](https://python-all.ru/3/library/functions.html#int), принимающей строку вида `'123'` и возвращающей её числовое значение 123. Если требуется сохранять более сложные типы данных, например вложенные списки и словари, ручной разбор и сериализация становятся сложными.362363Чтобы избавить пользователей от постоянного написания и отладки кода для сохранения сложных типов данных в файлы, Python позволяет использовать популярный формат обмена данными, называемый [JSON (JavaScript Object Notation)](https://python-all.ru/3/tutorial/inputoutput.html). Стандартный модуль [`json`](https://python-all.ru/3/library/json.html#module-json) может обрабатывать иерархии данных Python и преобразовывать их в строковые представления; этот процесс называется *сериализацией*. Восстановление данных из строкового представления называется *десериализацией*. Между сериализацией и десериализацией строка, представляющая объект, может быть сохранена в файл или данные, либо передана по сетевому соединению на удалённую машину.364365> **Примечание**366>367> Формат JSON широко используется в современных приложениях для обмена данными. Многие программисты уже знакомы с ним, что делает его хорошим выбором для обеспечения совместимости.368369Если у вас есть объект `x`, вы можете увидеть его строковое представление в JSON одной строкой кода:370371```python372>>> import json373>>> x = [1, 'simple', 'list']374>>> json.dumps(x)375'[1, "simple", "list"]'376```377378Другой вариант функции [`dumps()`](https://python-all.ru/3/library/json.html#json.dumps), называемый [`dump()`](https://python-all.ru/3/library/json.html#json.dump), просто сериализует объект в [текстовый файл](https://python-all.ru/3/glossary.html#term-text-file). Так что если `f` – это текстовый файл, открытый для записи, можно сделать так:379380```python381json.dump(x, f)382```383384Чтобы снова декодировать объект, если `f` – это [двоичный файл](https://python-all.ru/3/glossary.html#term-binary-file) или объект [текстового файла](https://python-all.ru/3/glossary.html#term-text-file), открытый для чтения:385386```python387x = json.load(f)388```389390> **Примечание**391>392> Файлы JSON должны быть закодированы в UTF-8. Используйте `encoding="utf-8"` при открытии JSON-файла как [текстового файла](https://python-all.ru/3/glossary.html#term-text-file) как для чтения, так и для записи.393394Этот простой метод сериализации может обрабатывать списки и словари, но для сериализации произвольных экземпляров классов в JSON требуется немного дополнительных усилий. В справочнике по модулю [`json`](https://python-all.ru/3/library/json.html#module-json) есть объяснение этого.395396> **См. также**397>398> [`pickle`](https://python-all.ru/3/library/pickle.html#module-pickle) – модуль pickle399>400> В отличие от [JSON](https://python-all.ru/3/tutorial/inputoutput.html#tut-json), *pickle* – это протокол, позволяющий сериализовывать произвольно сложные объекты Python. Поэтому он специфичен для Python и не может использоваться для взаимодействия с приложениями, написанными на других языках. Кроме того, по умолчанию он небезопасен: десериализация данных pickle из ненадёжного источника может выполнить произвольный код, если данные были подготовлены опытным злоумышленником.401