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

Ввод и выводInput and Output

Есть несколько способов отображения вывода программы: данные можно выводить в удобочитаемой форме или записывать в файл для последующего использования. В этой главе рассматриваются некоторые из возможностей.

Расширенное форматирование выводаFancier Output Formatting

До сих пор мы встречались с двумя способами вывода значений: выражения-инструкции и функция print(). (Третий способ – использовать метод write() файловых объектов; стандартный файл вывода можно указать как sys.stdout. Подробнее об этом см. в Справочнике по библиотеке.)

Часто возникает потребность в более тонком контроле форматирования вывода, а не просто в печати значений через пробел. Есть два способа форматировать вывод: первый – полностью обрабатывать строки самостоятельно; используя операции среза и конкатенации, можно создать любой макет, какой только можно вообразить. Стандартный модуль string содержит полезные функции для дополнения строк до заданной ширины столбца; о них речь пойдет ниже. Второй способ – использовать метод str.format().

Модуль string содержит класс Template, предоставляющий ещё один способ подстановки значений в строки.

Остаётся, конечно, один вопрос: как преобразовать значения в строки? К счастью, в Python есть способы преобразовать любое значение в строку: передать его функции repr() или str().

Функция str() предназначена для возврата представлений значений, которые достаточно удобочитаемы, в то время как repr() предназначена для генерации представлений, которые могут быть прочитаны интерпретатором (или вызовет SyntaxError, если нет эквивалентного синтаксиса). Для объектов, у которых нет специального представления для человеческого восприятия, str() вернёт то же значение, что и repr(). Многие значения, такие как числа или структуры, например списки и словари, имеют одинаковое представление при использовании любой функции. Строки и числа с плавающей запятой, в частности, имеют два различных представления.

Несколько примеров:

>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(0.1)
'0.1'
>>> repr(0.1)
'0.10000000000000001'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print(s)
The value of x is 32.5, and y is 40000...
>>> # repr() строки добавляет кавычки и обратную косую черту:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print(hellos)
'hello, world\n'
>>> # Аргументом repr() может быть любой объект Python:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

Вот два способа вывести таблицу квадратов и кубов:

>>> for x in range(1, 11):
...     print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
...     # Обратите внимание на использование 'end' в предыдущей строке
...     print(repr(x*x*x).rjust(4))
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

>>> for x in range(1, 11):
...     print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

(Обратите внимание, что в первом примере один пробел между столбцами добавляется из-за того, как работает print(): она всегда добавляет пробелы между своими аргументами.)

Этот пример демонстрирует метод rjust() строковых объектов, который выравнивает строку по правому краю в поле заданной ширины, дополняя её пробелами слева. Существуют аналогичные методы ljust() и center(). Эти методы ничего не выводят, а лишь возвращают новую строку. Если входная строка слишком длинная, они не обрезают её, а возвращают как есть; это нарушит выравнивание столбцов, но обычно это лучше, чем альтернатива с искажением значения. (Если обрезка действительно нужна, всегда можно добавить операцию среза, например x.ljust(n)[:n].)

Существует ещё один метод zfill(), который дополняет числовую строку слева нулями. Он учитывает знаки плюс и минус:

>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'

Базовое использование метода str.format() выглядит так:

>>> print('We are the {0} who say "{1}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"

Фигурные скобки и символы внутри них (называемые полями формата) заменяются объектами, переданными в метод format. Число в скобках указывает позицию объекта, переданного в метод format.

>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam

Если в методе format используются именованные аргументы, на их значения ссылаются по имени аргумента.

>>> print('This {food} is {adjective}.'.format(
...       food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.

Позиционные и именованные аргументы можно произвольно комбинировать:

>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
                                                       other='Georg'))
The story of Bill, Manfred, and Georg.

После имени поля может следовать необязательный ':' и спецификатор формата. Это также даёт больший контроль над форматированием значения. В следующем примере число Пи усекается до трёх знаков после запятой.

>>> import math
>>> print('The value of PI is approximately {0:.3f}.'.format(math.pi))
The value of PI is approximately 3.142.

Если после ':' указать целое число, это поле будет иметь минимальную ширину в указанное количество символов. Это удобно для создания красивых таблиц.:

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print('{0:10} ==> {1:10d}'.format(name, phone))
...
Jack       ==>       4098
Dcab       ==>       7678
Sjoerd     ==>       4127

Если у вас очень длинная строка форматирования, которую не хочется разбивать, было бы удобно ссылаться на переменные по имени, а не по позиции. Это можно сделать, просто передав словарь и используя квадратные скобки '[]' для доступа к ключам.

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
          'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

Это можно сделать также, передав таблицу в виде именованных аргументов с помощью нотации ‘**’.:

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

Это особенно полезно в сочетании с новой встроенной функцией vars(), которая возвращает словарь, содержащий все локальные переменные.

Полный обзор форматирования строк с помощью str.format() см. в разделе Синтаксис строк формата.

Старое форматирование строкOld string formatting

Оператор % также можно использовать для форматирования строк. Он интерпретирует левый аргумент как строку формата в стиле sprintf, которая применяется к правому аргументу, и возвращает строку, полученную в результате этой операции форматирования. Например:

>>> import math
>>> print('The value of PI is approximately %5.3f.' % math.pi)
The value of PI is approximately 3.142.

Поскольку str.format() появился относительно недавно, множество кода на Python всё ещё использует оператор %. Однако, поскольку старый стиль форматирования со временем будет удалён из языка, предпочтительнее использовать str.format().

Дополнительную информацию можно найти в разделе Старые операции форматирования строк.

Чтение и запись файловReading and Writing Files

Функция open() возвращает файловый объект и чаще всего используется с двумя аргументами: open(filename, mode).

>>> f = open('/tmp/workfile', 'w')

Первый аргумент – строка с именем файла. Второй аргумент – ещё одна строка из нескольких символов, описывающая способ использования файла. mode может быть 'r' для чтения, 'w' для записи (существующий файл с таким именем будет стёрт), 'a' открывает файл для добавления; любые записанные данные автоматически добавляются в конец. 'r+' открывает файл для чтения и записи. Аргумент mode необязателен; если он опущен, используется 'r'.

Обычно файлы открываются в текстовом режиме, то есть вы читаете и записываете строки в файл и из файла, которые закодированы в определённой кодировке (по умолчанию UTF-8). Добавление 'b' к режиму открывает файл в двоичном режиме: теперь данные читаются и записываются в виде объектов bytes. Этот режим следует использовать для всех файлов, которые не содержат текст.

В текстовом режиме по умолчанию зависимые от платформы окончания строк (\n в Unix, \r\n в Windows) преобразуются в просто \n при чтении и \n обратно в зависимые от платформы окончания строк при записи. Это неявное изменение данных файла подходит для текстовых файлов, но испортит двоичные данные, такие как в файлах JPEG или EXE. При чтении и записи таких файлов следует обязательно использовать двоичный режим.

Методы файловых объектовMethods of File Objects

В остальных примерах этого раздела предполагается, что файловый объект с именем f уже создан.

Чтобы прочитать содержимое файла, вызовите f.read(size), которая читает некоторое количество данных и возвращает их в виде строки или объекта bytes. size – необязательный числовой аргумент. Если size опущен или отрицателен, будет прочитано и возвращено всё содержимое файла; это ваша проблема, если файл вдвое больше памяти вашей машины. В противном случае читается и возвращается не более size байтов. Если достигнут конец файла, f.read() вернёт пустую строку ('').

>>> f.read()
'This is the entire file.\n'
>>> f.read()
''

f.readline() читает одну строку из файла; символ новой строки ( ) остаётся в конце строки и опускается только для последней строки файла, если файл не заканчивается символом новой строки. Это делает возвращаемое значение однозначным: если f.readline() возвращает пустую строку, достигнут конец файла, а пустая строка представляется как '\n' – строка, содержащая только один символ новой строки.

>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file\n'
>>> f.readline()
''

f.readlines() возвращает список, содержащий все строки данных из файла. Если указан необязательный параметр sizehint, он читает указанное количество байт из файла, а также ещё некоторое количество, достаточное для завершения строки, и возвращает строки из этого. Это часто используется для эффективного построчного чтения больших файлов без необходимости загружать весь файл в память. Возвращаются только полные строки.

>>> f.readlines()
['This is the first line of the file.\n', 'Second line of the file\n']

Альтернативный подход к чтению строк – это организация цикла по файловому объекту. Он эффективен по памяти, быстр и ведёт к более простому коду:

>>> for line in f:
...     print(line, end='')
...
This is the first line of the file.
Second line of the file

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

f.write(string) записывает содержимое string в файл, возвращая количество записанных символов.

>>> f.write('This is a test\n')
15

Чтобы записать что-то, отличное от строки, его сначала нужно преобразовать в строку:

>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)
18

f.tell() возвращает целое число, представляющее текущую позицию файлового объекта в файле, измеряемую в байтах от начала файла. Чтобы изменить позицию файлового объекта, используйте f.seek(offset, from_what). Позиция вычисляется как сумма offset и опорной точки; опорная точка выбирается аргументом from_what. Значение from_what, равное 0, задаёт начало файла, 1 – текущую позицию, а 2 – конец файла в качестве опорной точки. Значение from_what может быть опущено; по умолчанию оно равно 0, что соответствует началу файла.

>>> f = open('/tmp/workfile', 'rb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5)     # Перейти к 6-му байту в файле
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # Перейти к 3-му байту от конца
13
>>> f.read(1)
b'd'

В текстовых файлах (открытых без b в строке режима) разрешён только поиск относительно начала файла (исключение составляет поиск до самого конца файла с помощью seek(0, 2)).

Когда работа с файлом завершена, вызовите f.close(), чтобы закрыть его и освободить системные ресурсы, занятые открытым файлом. После вызова f.close() попытки использовать файловый объект будут автоматически завершаться неудачей.

>>> f.close()
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file

Хорошей практикой является использование ключевого слова with при работе с файловыми объектами. Его преимущество в том, что файл корректно закрывается после завершения блока, даже если в процессе возникло исключение. Кроме того, это гораздо короче, чем писать эквивалентные блоки try-finally:

>>> with open('/tmp/workfile', 'r') as f:
...     read_data = f.read()
>>> f.closed
True

Файловые объекты имеют некоторые дополнительные методы, такие как isatty() и truncate(), которые используются реже; обратитесь к справочнику по библиотеке для полного руководства по файловым объектам.

Модуль pickleThe pickle Module

Строки легко записываются и читаются из файла. С числами немного сложнее, поскольку метод read() возвращает только строки, которые нужно передать такой функции, как int(), которая принимает строку вида '123' и возвращает её числовое значение 123. Однако, когда нужно сохранить более сложные типы данных, такие как списки, словари или экземпляры классов, всё становится гораздо сложнее.

Вместо того чтобы постоянно писать и отлаживать код для сохранения сложных типов данных, Python предлагает стандартный модуль pickle. Это удивительный модуль, который может взять почти любой объект Python (даже некоторые формы кода Python!) и преобразовать его в строковое представление; этот процесс называется упаковкой в pickle (pickling). Восстановление объекта из строкового представления называется распаковкой из pickle (unpickling). Между упаковкой и распаковкой строковое представление объекта может быть сохранено в файл или данные, или передано по сетевому соединению на удалённую машину.

Если есть объект x и файловый объект f, открытый для записи, самый простой способ упаковать объект с помощью pickle занимает всего одну строку кода:

pickle.dump(x, f)

Чтобы снова распаковать объект, если f – это файловый объект, открытый для чтения:

x = pickle.load(f)

(Существуют и другие варианты, используемые при упаковке множества объектов или когда не хочется записывать упакованные данные в файл; обратитесь к полной dокументации модуля pickle в Python Library Reference.)

pickle – это стандартный способ создания объектов Python, которые могут быть сохранены и повторно использованы другими программами или при будущих запусках той же программы; технический термин для этого – постоянный объект (persistent object). Так как pickle так широко используется, многие авторы, пишущие расширения Python, заботятся о том, чтобы новые типы данных, такие как матрицы, могли быть правильно упакованы и распакованы с помощью pickle.