ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 829
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
Глава 16. Работа с файлами и каталогами
291
Функции, предназначенные для работы с каталогами, мы еще рассмотрим подробно в сле- дующих разделах. Сейчас же важно запомнить, что текущим рабочим каталогом будет каталог, из которого запускается файл, а не каталог, в котором расположен исполняе- мый файл. Кроме того, пути поиска файлов не имеют никакого отношения к путям поиска модулей.
Необязательный параметр mode в функции open()
может принимать следующие значения:
r
— только чтение (значение по умолчанию). После открытия файла указатель устанав- ливается на начало файла. Если файл не существует, возбуждается исключение
FileNotFoundError
;
r+
— чтение и запись. После открытия файла указатель устанавливается на начало фай- ла. Если файл не существует, то возбуждается исключение
FileNotFoundError
;
w
— запись. Если файл не существует, он будет создан. Если файл существует, он будет перезаписан. После открытия файла указатель устанавливается на начало файла;
w+
— чтение и запись. Если файл не существует, он будет создан. Если файл существует, он будет перезаписан. После открытия файла указатель устанавливается на начало файла;
a
— запись. Если файл не существует, он будет создан. Запись осуществляется в конец файла. Содержимое файла не удаляется;
a+
— чтение и запись. Если файл не существует, он будет создан. Запись осуществляется в конец файла. Содержимое файла не удаляется;
x
— создание файла для записи. Если файл уже существует, возбуждается исключение
FileExistsError
;
x+
— создание файла для чтения и записи. Если файл уже существует, возбуждается ис- ключение
FileExistsError
После указания режима может следовать модификатор:
b
— файл будет открыт в бинарном режиме. Файловые методы принимают и возвраща- ют объекты типа bytes
;
t
— файл будет открыт в текстовом режиме (значение по умолчанию в Windows). Фай- ловые методы принимают и возвращают объекты типа str
. В этом режиме будет автома- тически выполняться обработка символа конца строки — так, в Windows при чтении вместо символов
\r\n будет подставлен символ
\n
. Для примера создадим файл file.txt и запишем в него две строки:
>>> f = open(r"file.txt", "w") # Открываем файл на запись
>>> f.write("String1\nString2") # Записываем две строки в файл
15
>>> f.close() # Закрываем файл
Поскольку мы указали режим w
, то, если файл не существует, он будет создан, а если существует, то будет перезаписан.
Теперь выведем содержимое файла в бинарном и текстовом режимах:
>>> # Бинарный режим (символ \r остается)
>>> with open(r"file.txt", "rb") as f: for line in f: print(repr(line)) b'String1\r\n' b'String2'
1 ... 24 25 26 27 28 29 30 31 ... 83
292
Часть I. Основы языка Python
>>> # Текстовый режим (символ \r удаляется)
>>> with open(r"file.txt", "r") as f: for line in f: print(repr(line))
'String1\n'
'String2'
Для ускорения работы производится буферизация записываемых данных. Информация из буфера записывается в файл полностью только в момент закрытия файла или после вызова функции или метода flush()
. В необязательном параметре buffering можно указать размер буфера. Если в качестве значения указан
0
, то данные будут сразу записываться в файл
(значение допустимо только в бинарном режиме). Значение
1
используется при построчной записи в файл (значение допустимо только в текстовом режиме), другое положительное число задает примерный размер буфера, а отрицательное значение (или отсутствие значе- ния) означает установку размера, применяемого в системе по умолчанию. По умолчанию текстовые файлы буферизуются построчно, а бинарные — частями, размер которых интер- претатор выбирает самостоятельно в диапазоне от 4096 до 8192 байтов.
При использовании текстового режима (задается по умолчанию) при чтении производится попытка преобразовать данные в кодировку Unicode, а при записи выполняется обратная операция — строка преобразуется в последовательность байтов в определенной кодировке.
По умолчанию назначается кодировка, применяемая в системе. Если преобразование невоз- можно, возбуждается исключение. Указать кодировку, которая будет использоваться при записи и чтении файла, позволяет параметр encoding
. Для примера запишем данные в коди- ровке UTF-8:
>>> f = open(r"file.txt", "w", encoding="utf-8")
>>> f.write("Строка") # Записываем строку в файл
6
>>> f.close() # Закрываем файл
Для чтения этого файла следует явно указать кодировку при открытии файла:
>>> with open(r"file.txt", "r", encoding="utf-8") as f: for line in f: print(line)
Строка
При работе с файлами в кодировках UTF-8, UTF-16 и UTF-32 следует учитывать, что в на- чале файла могут присутствовать служебные символы, называемые сокращенно BOM (Byte
Order Mark, метка порядка байтов). Для кодировки UTF-8 эти символы являются необяза- тельными, и в предыдущем примере они не были добавлены в файл при записи. Чтобы сим- волы были добавлены, в параметре encoding следует указать значение utf-8-sig
. Запишем строку в файл в кодировке UTF-8 с BOM:
>>> f = open(r"file.txt", "w", encoding="utf-8-sig")
>>> f.write("Строка") # Записываем строку в файл
6
>>> f.close() # Закрываем файл
Теперь прочитаем файл с разными значениями в параметре encoding
:
>>> with open(r"file.txt", "r", encoding="utf-8") as f: for line in f: print(repr(line))
Глава 16. Работа с файлами и каталогами
293
'\ufeffСтрока'
>>> with open(r"file.txt", "r", encoding="utf-8-sig") as f: for line in f: print(repr(line))
'Строка'
В первом примере мы указали значение utf-8
, поэтому маркер BOM был прочитан из файла вместе с данными. Во втором примере указано значение utf-8-sig
, поэтому маркер BOM не попал в результат. Если неизвестно, есть ли маркер в файле, и необходимо получить данные без маркера, то следует всегда указывать значение utf-8-sig при чтении файла в кодировке
UTF-8.
Для кодировок UTF-16 и UTF-32 маркер BOM является обязательным. При указании значе- ний utf-16
и utf-32
в параметре encoding обработка маркера производится автоматически.
При записи данных маркер автоматически вставляется в начало файла, а при чтении он не попадает в результат. Запишем строку в файл, а затем прочитаем ее из файла:
>>> with open(r"file.txt", "w", encoding="utf-16") as f: f.write("Строка")
6
>>> with open(r"file.txt", "r", encoding="utf-16") as f: for line in f: print(repr(line))
'Строка'
При использовании значений utf-16-le
, utf-16-be
, utf-32-le и utf-32-be маркер BOM не- обходимо самим добавить в начало файла, а при чтении удалить его.
В параметре errors можно указать уровень обработки ошибок. Возможные значения:
"strict"
(при ошибке возбуждается исключение
ValueError
— значение по умолчанию),
"replace"
(неизвестный символ заменяется символом вопроса или символом с кодом
\ufffd
),
"ignore"
(неизвестные символы игнорируются),
"xmlcharrefreplace"
(неизвестный символ заменяется последовательностью
xxx;
) и "backslashreplace"
(неизвестный сим- вол заменяется последовательностью
\uxxxx
).
Параметр newline задает режим обработки символов конца строк. Поддерживаемые им зна- чения таковы:
None
(значение по умолчанию) — выполняется стандартная обработка символов конца строки. Например, в Windows при чтении символы
\r\n преобразуются в символ
\n
, а при записи производится обратное преобразование;
""
(пустая строка) — обработка символов конца строки не выполняется;
"<Специальный символ>"
— указанный специальный символ используется для обозначе- ния конца строки, и никакая дополнительная обработка не выполняется. В качестве спе- циального символа можно указать лишь
\r\n
,
\r и
\n
16.2. Методы для работы с файлами
После открытия файла функция open()
возвращает объект, с помощью которого произво- дится дальнейшая работа с файлом. Тип объекта зависит от режима открытия файла и буферизации. Рассмотрим основные методы:
294
Часть I. Основы языка Python
close()
— закрывает файл. Так как интерпретатор автоматически удаляет объект, когда на него отсутствуют ссылки, в небольших программах файл можно не закрывать явно.
Тем не менее, явное закрытие файла является признаком хорошего стиля программи- рования. Кроме того, при наличии незакрытого файла генерируется предупреждающее сообщение:
"ResourceWarning: unclosed file"
Язык Python поддерживает протокол менеджеров контекста. Этот протокол гарантирует закрытие файла вне зависимости от того, произошло исключение внутри блока кода или нет: with open(r"file.txt", "w", encoding="cp1251") as f: f.write("Строка") # Записываем строку в файл
# Здесь файл уже закрыт автоматически
write(<Данные>)
— записывает данные в файл. Если в качестве параметра указана стро- ка, файл должен быть открыт в текстовом режиме, а если указана последовательность байтов — в бинарном. Помните, что нельзя записывать строку в бинарном режиме и по- следовательность байтов в текстовом режиме. Метод возвращает количество записанных символов или байтов. Пример записи в файл:
>>> # Текстовый режим
>>> f = open(r"file.txt", "w", encoding="cp1251")
>>> f.write("Строка1\nСтрока2") # Записываем строку в файл
15
>>> f.close() # Закрываем файл
>>> # Бинарный режим
>>> f = open(r"file.txt", "wb")
>>> f.write(bytes("Строка1\nСтрока2", "cp1251"))
15
>>> f.write(bytearray("\nСтрока3", "cp1251"))
8
>>> f.close()
writelines(<Последовательность>)
— записывает последовательность в файл. Если все элементы последовательности являются строками, файл должен быть открыт в тексто- вом режиме. Если все элементы являются последовательностями байтов, то файл должен быть открыт в бинарном режиме. Пример записи элементов списка:
>>> # Текстовый режим
>>> f = open(r"file.txt", "w", encoding="cp1251")
>>> f.writelines(["Строка1\n", "Строка2"])
>>> f.close()
>>> # Бинарный режим
>>> f = open(r"file.txt", "wb")
>>> arr = [bytes("Строка1\n", "cp1251"), bytes("Строка2", "cp1251")]
>>> f.writelines(arr)
>>> f.close()
writable()
— возвращает
True
, если файл поддерживает запись, и
False
— в противном случае:
>>> f = open(r"file.txt", "r") # Открываем файл для чтения
>>> f.writable()
False
Глава 16. Работа с файлами и каталогами
295
>>> f = open(r"file.txt", "w") # Открываем файл для записи
>>> f.writable()
True
read([<Количество>])
— считывает данные из файла. Если файл открыт в текстовом режиме, возвращается строка, а если в бинарном — последовательность байтов. Если параметр не указан, возвращается содержимое файла от текущей позиции указателя до конца файла:
>>> # Текстовый режим
>>> with open(r"file.txt", "r", encoding="cp1251") as f: f.read()
'Строка1\nСтрока2'
>>> # Бинарный режим
>>> with open(r"file.txt", "rb") as f: f.read() b'\xd1\xf2\xf0\xee\xea\xe01\n\xd1\xf2\xf0\xee\xea\xe02'
Если в качестве параметра указать число, то за каждый вызов будет возвращаться ука- занное количество символов или байтов. Когда достигается конец файла, метод возвра- щает пустую строку:
>>> # Текстовый режим
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> f.read(8) # Считываем 8 символов 'Строка1\n'
>>> f.read(8) # Считываем 8 символов 'Строка2'
>>> f.read(8) # Достигнут конец файла ''
>>> f.close()
readline([<Количество>])
— считывает из файла одну строку при каждом вызове. Если файл открыт в текстовом режиме, возвращается строка, а если в бинарном — последова- тельность байтов. Возвращаемая строка включает символ перевода строки. Исключени- ем является последняя строка — если она не завершается символом перевода строки, то таковой добавлен не будет. При достижении конца файла возвращается пустая строка:
>>> # Текстовый режим
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> f.readline(), f.readline()
('Строка1\n', 'Строка2')
>>> f.readline() # Достигнут конец файла ''
>>> f.close()
>>> # Бинарный режим
>>> f = open(r"file.txt", "rb")
>>> f.readline(), f.readline()
(b'\xd1\xf2\xf0\xee\xea\xe01\n', b'\xd1\xf2\xf0\xee\xea\xe02')
>>> f.readline() # Достигнут конец файла b''
>>> f.close()
296
Часть I. Основы языка Python
Если в необязательном параметре указано число, считывание будет выполняться до тех пор, пока не встретится символ новой строки (
\n
), символ конца файла или из файла не будет прочитано указанное количество символов. Иными словами, если количество сим- волов в строке меньше значения параметра, то будет считана одна строка, а не указанное количество символов, а если количество символов в строке больше, то возвращается указанное количество символов:
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> f.readline(2), f.readline(2)
('Ст', 'ро')
>>> f.readline(100) # Возвращается одна строка, а не 100 символов 'ка1\n'
>>> f.close()
readlines()
— считывает все содержимое файла в список. Каждый элемент списка бу- дет содержать одну строку, включая символ перевода строки. Исключением является последняя строка — если она не завершается символом перевода строки, таковой добав- лен не будет. Если файл открыт в текстовом режиме, возвращается список строк, а если в бинарном — список объектов типа bytes
:
>>> # Текстовый режим
>>> with open(r"file.txt", "r", encoding="cp1251") as f: f.readlines()
['Строка1\n', 'Строка2']
>>> # Бинарный режим
>>> with open(r"file.txt", "rb") as f: f.readlines()
[b'\xd1\xf2\xf0\xee\xea\xe01\n', b'\xd1\xf2\xf0\xee\xea\xe02']
__next__()
— считывает одну строку при каждом вызове. Если файл открыт в текстовом режиме, возвращается строка, а если в бинарном — последовательность байтов. При достижении конца файла возбуждается исключение
StopIteration
:
>>> # Текстовый режим
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> f.__next__(), f.__next__()
('Строка1\n', 'Строка2')
>>> f.__next__() # Достигнут конец файла
Traceback (most recent call last):
File "
", line 1, in
StopIteration
>>> f.close()
Благодаря методу
__next__()
мы можем перебирать файл построчно в цикле for
. Цикл for на каждой итерации будет автоматически вызывать метод
__next__()
. Для примера выведем все строки, предварительно удалив символ перевода строки:
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> for line in f: print(line.rstrip("\n"), end=" ")
Строка1 Строка2
>>> f.close()
Глава 16. Работа с файлами и каталогами
297
flush()
— принудительно записывает данные из буфера на диск;
fileno()
— возвращает целочисленный дескриптор файла. Возвращаемое значение все- гда будет больше числа 2, т. к. число 0 закреплено за стандартным вводом stdin
, 1 — за стандартным выводом stdout
, а 2 — за стандартным выводом сообщений об ошибках stderr
:
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> f.fileno() # Дескриптор файла
3
>>> f.close()
truncate([<Количество>])
— обрезает файл до указанного количества символов (если задан текстовый режим) или байтов (в случае бинарного режима). Метод возвращает новый размер файла:
>>> f = open(r"file.txt", "r+", encoding="cp1251")
>>> f.read()
'Строка1\nСтрока2'
>>> f.truncate(5)
5
>>> f.close()
>>> with open(r"file.txt", "r", encoding="cp1251") as f: f.read()
'Строк'
tell()
— возвращает позицию указателя относительно начала файла в виде целого чис- ла. Обратите внимание на то, что в Windows метод tell()
считает символ
\r как допол- нительный байт, хотя этот символ удаляется при открытии файла в текстовом режиме:
>>> with open(r"file.txt", "w", encoding="cp1251") as f: f.write("String1\nString2")
15
>>> f = open(r"file.txt", "r", encoding="cp1251")
>>> f.tell() # Указатель расположен в начале файла
0
>>> f.readline() # Перемещаем указатель 'String1\n'
>>> f.tell() # Возвращает 9 (8 + '\r'), а не 8 !!!
9
>>> f.close()
Чтобы избежать этого несоответствия, следует открывать файл в бинарном режиме, а не в текстовом:
>>> f = open(r"file.txt", "rb")
>>> f.readline() # Перемещаем указатель b'String1\r\n'
>>> f.tell() # Теперь значение соответствует
9
>>> f.close()
298
Часть I. Основы языка Python
seek(<Смещение>[, <Позиция>])
— устанавливает указатель в позицию, имеющую за- данное
<Смещение>
относительно параметра
<Позиция>
. В качестве параметра
<Позиция>
могут быть указаны следующие атрибуты из модуля io или соответствующие им значе- ния:
• io.SEEK_SET
или
0
— начало файла (значение по умолчанию);
• io.SEEK_CUR
или
1
— текущая позиция указателя. Положительное значение смещения вызывает перемещение к концу файла, отрицательное — к его началу;
• io.SEEK_END
или
2
— конец файла.
Выведем значения этих атрибутов:
>>> import io
>>> io.SEEK_SET, io.SEEK_CUR, io.SEEK_END
(0, 1, 2)
Пример использования метода seek()
:
>>> import io
>>> f = open(r"file.txt", "rb")
>>> f.seek(9, io.SEEK_CUR) # 9 байтов от указателя
9
>>> f.tell()
9
>>> f.seek(0, io.SEEK_SET) # Перемещаем указатель в начало
0
>>> f.tell()
0
>>> f.seek(-9, io.SEEK_END) # -9 байтов от конца файла
7
>>> f.tell()
7
>>> f.close()
seekable()
— возвращает
True
, если указатель файла можно сдвинуть в другую пози- цию, и
False
— в противном случае:
>>> f = open(r"C:\temp\new\file.txt", "r")
>>> f.seekable()
True
Помимо методов, объекты файлов поддерживают несколько атрибутов:
name
— имя файла;
mode
— режим, в котором был открыт файл;
closed
— возвращает
True
, если файл был закрыт, и
False
— в противном случае:
>>> f = open(r"file.txt", "r+b")
>>> f.name, f.mode, f.closed
('file.txt', 'rb+', False)
>>> f.close()
>>> f.closed
True