9. Ввод-вывод.

Способы вывода

Строковое представление

В Python есть два способа для преобразования любого значения в строку — это функции repr() и str().

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

Запись и чтение файлов

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

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

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

В обычном случае файлы открываются в текстовом режиме (text mode) — это значит что вы читаете из файла и записываете в файл строки в определённой кодировке (по умолчанию используется UTF-8). Если добавить к режиму файла символ ‘b’, файл открывается в двоичном режиме (binary mode): теперь данные считываются и записываются в виде двоичных объектов. Этот режим следует использовать для всех файлов, которые не содержат текст.

Методы объектов-файлов

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

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

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

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

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

for line in f:
    print(line, end='')

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

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

Чтобы записать в файл нечто отличное от строки, предварительно это нечто нужно в строку сконвертировать:

value = ('ответ', 42)
s = str(value)
f.write(s)
18

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

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

При работе с текстовыми файлами (открытыми без символа b в строке режима), выполнять позиционирование (seek) позволяется только от начала файла (за исключением прокрутки в конец файла с использованием 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(), которые используются не так часто; обратитесь к Справочнику по библиотеке для более полного обзора по файловым объектам.