ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 864
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
Глава 16. Работа с файлами и каталогами
299
encoding
— название кодировки, которая будет использоваться для преобразования строк перед записью в файл или при чтении. Атрибут доступен только в текстовом режиме. Обратите также внимание на то, что изменить значение атрибута нельзя, поскольку он доступен только для чтения:
>>> f = open(r"file.txt", "a", encoding="cp1251")
>>> f.encoding
'cp1251'
>>> f.close()
Стандартный вывод stdout также является файловым объектом. Атрибут encoding этого объекта всегда содержит кодировку устройства вывода, поэтому строка преобразуется в последовательность байтов в правильной кодировке. Например, при запуске с помощью двойного щелчка на значке файла атрибут encoding будет иметь значение "cp866"
, а при запуске в окне Python Shell редактора IDLE — значение "cp1251"
:
>>> import sys
>>> sys.stdout.encoding
'cp1251'
buffer
— позволяет получить доступ к буферу. Атрибут доступен только в текстовом режиме. С помощью этого объекта можно записать последовательность байтов в тексто- вый поток:
>>> f = open(r"file.txt", "w", encoding="cp1251")
>>> f.buffer.write(bytes("Строка", "cp1251"))
6
>>> f.close()
16.3. Доступ к файлам с помощью модуля os
Модуль os содержит дополнительные низкоуровневые функции, позволяющие работать с файлами. Функциональность этого модуля зависит от используемой операционной систе- мы. Получить название используемой версии модуля можно с помощью атрибута name
В любой из поддерживаемых Python версий операционной системы Windows этот атрибут возвращает значение "nt"
:
>>> import os
>>> os.name # Значение в ОС Windows 8
'nt'
Для доступа к файлам предназначены следующие функции из модуля os
:
open(<Путь к файлу>, <Режим>[, mode=0o777])
— открывает файл и возвращает цело- численный дескриптор, с помощью которого производится дальнейшая работа с файлом.
Если файл открыть не удалось, возбуждается исключение
OSError или одно из исключе- ний, являющихся его подклассами (мы поговорим о них в конце этой главы). В парамет- ре
<Режим>
в операционной системе Windows могут быть указаны следующие флаги (или их комбинация через символ
|
):
• os.O_RDONLY
— чтение;
• os.O_WRONLY
— запись;
• os.O_RDWR
— чтение и запись;
• os.O_APPEND
— добавление в конец файла;
300
Часть I. Основы языка Python
• os.O_CREAT
— создать файл, если он не существует и если не указан флаг os.O_EXCL
;
• os.O_EXCL
— при использовании совместно с os.O_CREAT
указывает, что создаваемый файл изначально не должен существовать, в противном случае будет сгенерировано исключение
1 ... 25 26 27 28 29 30 31 32 ... 83
FileExistsError
;
• os.O_TEMPORARY
— при использовании совместно с os.O_CREAT
указывает, что созда- ется временный файл, который будет автоматически удален сразу после закрытия;
• os.O_SHORT_LIVED
— то же самое, что os.O_TEMPORARY
, но созданный файл по возмож- ности будет храниться лишь в оперативной памяти, а не на диске;
• os.O_TRUNC
— очистить содержимое файла;
• os.O_BINARY
— файл будет открыт в бинарном режиме;
• os.O_TEXT
— файл будет открыт в текстовом режиме (в Windows файлы открываются в текстовом режиме по умолчанию).
Рассмотрим несколько примеров:
• откроем файл на запись и запишем в него одну строку. Если файл не существует, создадим его. Если файл существует, очистим его:
>>> import os # Подключаем модуль
>>> mode = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
>>> f = os.open(r"file.txt", mode)
>>> os.write(f, b"String1\n") # Записываем данные
8
>>> os.close(f) # Закрываем файл
• добавим еще одну строку в конец файла:
>>> mode = os.O_WRONLY | os.O_CREAT | os.O_APPEND
>>> f = os.open(r"file.txt", mode)
>>> os.write(f, b"String2\n") # Записываем данные
8
>>> os.close(f) # Закрываем файл
• прочитаем содержимое файла в текстовом режиме:
>>> f = os.open(r"file.txt", os.O_RDONLY)
>>> os.read(f, 50) # Читаем 50 байтов b'String1\nString2\n'
>>> os.close(f) # Закрываем файл
• теперь прочитаем содержимое файла в бинарном режиме:
>>> f = os.open(r"file.txt", os.O_RDONLY | os.O_BINARY)
>>> os.read(f, 50) # Читаем 50 байтов b'String1\r\nString2\r\n'
>>> os.close(f) # Закрываем файл
read(<Дескриптор>, <Количество байтов>)
— читает из файла указанное количество байтов. При достижении конца файла возвращается пустая строка:
>>> f = os.open(r"file.txt", os.O_RDONLY)
>>> os.read(f, 5), os.read(f, 5), os.read(f, 5), os.read(f, 5)
(b'Strin', b'g1\nS', b'tring', b'2\n')
Глава 16. Работа с файлами и каталогами
301
>>> os.read(f, 5) # Достигнут конец файла b''
>>> os.close(f) # Закрываем файл
write(<Дескриптор>, <Последовательность байтов>)
— записывает последовательность байтов в файл. Возвращает количество записанных байтов;
close(<Дескриптор>)
— закрывает файл;
lseek(<Дескриптор>, <Смещение>, <Позиция>)
— устанавливает указатель в позицию, имеющую заданное
<Смещение> относительно параметра
<Позиция>
. Возвращает новую позицию указателя. В качестве параметра
<Позиция>
могут быть указаны следующие атрибуты или соответствующие им значения:
• os.SEEK_SET
или
0
— начало файла;
• os.SEEK_CUR
или
1
— текущая позиция указателя;
• os.SEEK_END
или
2
— конец файла.
Пример:
>>> f = os.open(r"file.txt", os.O_RDONLY | os.O_BINARY)
>>> os.lseek(f, 0, os.SEEK_END) # Перемещение в конец файла
18
>>> os.lseek(f, 0, os.SEEK_SET) # Перемещение в начало файла
0
>>> os.lseek(f, 9, os.SEEK_CUR) # Относительно указателя
9
>>> os.lseek(f, 0, os.SEEK_CUR) # Текущее положение указателя
9
>>> os.close(f) # Закрываем файл
dup(<Дескриптор>)
— возвращает дубликат файлового дескриптора;
fdopen(<Дескриптор>[, <Режим>[, <Размер буфера>]])
— возвращает файловый объект по указанному дескриптору. Параметры
<Режим>
и
<Размер буфера>
имеют тот же смысл, что и в функции open()
:
>>> fd = os.open(r"file.txt", os.O_RDONLY)
>>> fd
3
>>> f = os.fdopen(fd, "r")
>>> f.fileno() # Объект имеет тот же дескриптор
3
>>> f.read()
'String1\nString2\n'
>>> f.close()
16.4. Классы StringIO и BytesIO
Класс
StringIO
из модуля io позволяет работать со строкой как с файловым объектом. Все операции с этим файловым объектом (будем называть его далее «файл») производятся в оперативной памяти. Формат конструктора класса:
StringIO([<Начальное значение>][, newline=None])
302
Часть I. Основы языка Python
Если первый параметр не указан, то начальным значением будет пустая строка. После соз- дания объекта указатель текущей позиции устанавливается на начало «файла». Объект, воз- вращаемый конструктором класса, имеет следующие методы:
close()
— закрывает «файл». Проверить, открыт «файл» или закрыт, позволяет атрибут closed
. Атрибут возвращает
True
, если «файл» был закрыт, и
False
— в противном слу- чае;
getvalue()
— возвращает содержимое «файла» в виде строки:
>>> import io # Подключаем модуль
>>> f = io.StringIO("String1\n")
>>> f.getvalue() # Получаем содержимое «файла»
'String1\n'
>>> f.close() # Закрываем «файл»
tell()
— возвращает текущую позицию указателя относительно начала «файла»;
seek(<Смещение>[, <Позиция>])
— устанавливает указатель в позицию, имеющую за- данное
<Смещение> относительно параметра
<Позиция>
. В качестве параметра
<Позиция>
могут быть указаны следующие значения:
•
0
— начало «файла» (значение по умолчанию);
•
1
— текущая позиция указателя;
•
2
— конец «файла».
Пример использования методов seek()
и tell()
:
>>> f = io.StringIO("String1\n")
>>> f.tell() # Позиция указателя
0
>>> f.seek(0, 2) # Перемещаем указатель в конец «файла»
8
>>> f.tell() # Позиция указателя
8
>>> f.seek(0) # Перемещаем указатель в начало «файла»
0
>>> f.tell() # Позиция указателя
0
>>> f.close() # Закрываем файл
write(<Строка>)
— записывает строку в «файл»:
>>> f = io.StringIO("String1\n")
>>> f.seek(0, 2) # Перемещаем указатель в конец «файла»
8
>>> f.write("String2\n") # Записываем строку в «файл»
8
>>> f.getvalue() # Получаем содержимое «файла»
'String1\nString2\n'
>>> f.close() # Закрываем «файл»
writelines(<Последовательность>)
— записывает последовательность в «файл»:
>>> f = io.StringIO()
>>> f.writelines(["String1\n", "String2\n"])
Глава 16. Работа с файлами и каталогами
303
>>> f.getvalue() # Получаем содержимое «файла»
'String1\nString2\n'
>>> f.close() # Закрываем «файл»
read([<Количество символов>])
— считывает данные из «файла». Если параметр не ука- зан, возвращается содержимое «файла» от текущей позиции указателя до конца «файла».
Если в качестве параметра указать число, то за каждый вызов будет возвращаться указанное количество символов. Когда достигается конец «файла», метод возвращает пустую строку:
>>> f = io.StringIO("String1\nString2\n")
>>> f.read()
'String1\nString2\n'
>>> f.seek(0) # Перемещаем указатель в начало «файла»
0
>>> f.read(5), f.read(5), f.read(5), f.read(5), f.read(5)
('Strin', 'g1\nSt', 'ring2', '\n', '')
>>> f.close() # Закрываем «файл»
readline([<Количество символов>])
— считывает из «файла» одну строку при каждом вызове. Возвращаемая строка включает символ перевода строки. Исключением является последняя строка — если она не завершается символом перевода строки, таковой добав- лен не будет. При достижении конца «файла» возвращается пустая строка:
>>> f = io.StringIO("String1\nString2")
>>> f.readline(), f.readline(), f.readline()
('String1\n', 'String2', '')
>>> f.close() # Закрываем «файл»
Если в необязательном параметре указано число, считывание будет выполняться до тех пор, пока не встретится символ новой строки (
\n
), символ конца «файла» или из «файла» не будет прочитано указанное количество символов. Иными словами, если количество символов в строке меньше значения параметра, будет считана одна строка, а не указан- ное количество символов. Если количество символов в строке больше, возвращается указанное количество символов:
>>> f = io.StringIO("String1\nString2\nString3\n")
>>> f.readline(5), f.readline(5)
('Strin', 'g1\n')
>>> f.readline(100) # Возвращается одна строка, а не 100 символов 'String2\n'
>>> f.close() # Закрываем «файл»
readlines([<Примерное количество символов>])
— считывает все содержимое «файла» в список. Каждый элемент списка будет содержать одну строку, включая символ пере- вода строки. Исключением является последняя строка — если она не завершается сим- волом перевода строки, таковой добавлен не будет:
>>> f = io.StringIO("String1\nString2\nString3")
>>> f.readlines()
['String1\n', 'String2\n', 'String3']
>>> f.close() # Закрываем «файл»
Если в необязательном параметре указано число, считывается указанное количество символов плюс фрагмент до символа конца строки
\n
. Затем эта строка разбивается и добавляется построчно в список:
304
Часть I. Основы языка Python
>>> f = io.StringIO("String1\nString2\nString3")
>>> f.readlines(14)
['String1\n', 'String2\n']
>>> f.seek(0) # Перемещаем указатель в начало «файла»
0
>>> f.readlines(17)
['String1\n', 'String2\n', 'String3']
>>> f.close() # Закрываем «файл»
__next__()
— считывает одну строку при каждом вызове. При достижении конца «фай- ла» возбуждается исключение
StopIteration
:
>>> f = io.StringIO("String1\nString2")
>>> f.__next__(), f.__next__()
('String1\n', 'String2')
>>> f.__next__()
... Фрагмент опущен ...
StopIteration
>>> f.close() # Закрываем «файл»
Благодаря методу
__next__()
мы можем перебирать файл построчно с помощью цикла for
. Цикл for на каждой итерации будет автоматически вызывать метод
__next__()
:
>>> f = io.StringIO("String1\nString2")
>>> for line in f: print(line.rstrip())
String1
String2
>>> f.close() # Закрываем «файл»
flush()
— сбрасывает данные из буфера в «файл»;
truncate([<Количество символов>])
— обрезает «файл» до указанного количества сим- волов:
>>> f = io.StringIO("String1\nString2\nString3")
>>> f.truncate(15) # Обрезаем «файл»
15
>>> f.getvalue() # Получаем содержимое «файла»
'String1\nString2'
>>> f.close() # Закрываем «файл»
Если параметр не указан, то «файл» обрезается до текущей позиции указателя:
>>> f = io.StringIO("String1\nString2\nString3")
>>> f.seek(15) # Перемещаем указатель
15
>>> f.truncate() # Обрезаем «файл» до указателя
15
>>> f.getvalue() # Получаем содержимое «файла»
'String1\nString2'
>>> f.close() # Закрываем «файл»
Описанные ранее методы writable()
и seekable()
, вызванные у объекта класса
StringIO
, всегда возвращают
True
Глава 16. Работа с файлами и каталогами
305
Класс
StringIO
работает только со строками. Чтобы выполнять аналогичные операции с «файлами», представляющими собой последовательности байтов, следует использовать класс
BytesIO
из модуля io
. Формат конструктора класса:
BytesIO([<Начальное значение>])
Класс
BytesIO
поддерживает такие же методы, что и класс
StringIO
, но в качестве значений методы принимают и возвращают последовательности байтов, а не строки. Рассмотрим основные операции на примере:
>>> import io # Подключаем модуль
>>> f = io.BytesIO(b"String1\n")
>>> f.seek(0, 2) # Перемещаем указатель в конец файла
8
>>> f.write(b"String2\n") # Пишем в файл
8
>>> f.getvalue() # Получаем содержимое файла b'String1\nString2\n'
>>> f.seek(0) # Перемещаем указатель в начало файла
0
>>> f.read() # Считываем данные b'String1\nString2\n'
>>> f.close() # Закрываем файл
Класс
BytesIO
поддерживает также метод getbuffer()
, который возвращает ссылку на объ- ект memoryview
. С помощью этого объекта можно получать и изменять данные по индексу или срезу, преобразовывать данные в список целых чисел (с помощью метода tolist()
) или в последовательность байтов (с помощью метода tobytes()
):
>>> f = io.BytesIO(b"Python")
>>> buf = f.getbuffer()
>>> buf[0] # Получаем значение по индексу b'P'
>>> buf[0] = b"J" # Изменяем значение по индексу
>>> f.getvalue() # Получаем содержимое b'Jython'
>>> buf.tolist() # Преобразуем в список чисел
[74, 121, 116, 104, 111, 110]
>>> buf.tobytes() # Преобразуем в тип bytes b'Jython'
>>> f.close() # Закрываем файл
16.5. Права доступа к файлам и каталогам
В операционных системах семейства UNIX каждому объекту (файлу или каталогу) назна- чаются права доступа, предоставляемые той или иной разновидности пользователей: вла- дельцу, группе и прочим. Могут быть назначены следующие права доступа:
чтение;
запись;
выполнение.
306
Часть I. Основы языка Python
Права доступа обозначаются буквами:
r
— файл можно читать, а содержимое каталога можно просматривать;
w
— файл можно модифицировать, удалять и переименовывать, а в каталоге можно соз- давать или удалять файлы. Каталог можно переименовать или удалить;
x
— файл можно выполнять, а в каталоге можно выполнять операции над файлами, в том числе производить в нем поиск файлов.
Права доступа к файлу определяются записью типа:
-rw-r--r--
Первый символ (
-
) означает, что это файл, и не задает никаких прав доступа. Далее три символа (
rw-
) задают права доступа для владельца: чтение и запись, символ (
-
) здесь означа- ет, что права на выполнение нет. Следующие три символа задают права доступа для группы
(
r--
) — здесь только чтение. Ну и последние три символа (
r--
) задают права для всех остальных пользователей — также только чтение.
Права доступа к каталогу определяются такой строкой: drwxr-xr-x
Первая буква (
d
) означает, что это каталог. Владелец может выполнять в каталоге любые действия (
rwx
), а группа и все остальные пользователи — только читать и выполнять поиск
(
r-x
). Для того чтобы каталог можно было просматривать, должны быть установлены права на выполнение (
x
).
Права доступа могут обозначаться и числом. Такие числа называются маской прав доступа.
Число состоит из трех цифр: от 0 до 7. Первая цифра задает права для владельца, вторая — для группы, а третья — для всех остальных пользователей. Например, права доступа
-rw-r-
-r-- соответствуют числу 644. Сопоставим числам, входящим в маску прав доступа, двоич- ную и буквенную записи (табл. 16.1).
Таблица 16.1. Права доступа в разных записях
Восьмеричная цифра
Двоичная запись
Буквенная запись
Восьмеричная цифра
Двоичная запись
Буквенная запись
0 000
---
4 100 r--
1 001
--x
5 101 r-x
2 010
-w-
6 110 rw-
3 011
-wx
7 111 rwx
Теперь понятно, что, согласно данным этой таблицы, права доступа rw-r--r-- можно запи- сать так: 110 100 100, что и переводится в число 644. Таким образом, если право предостав- лено, то в соответствующей позиции стоит 1, а если нет — то 0.
Для определения прав доступа к файлу или каталогу предназначена функция access()
из модуля os
. Функция имеет следующий формат: access(<Путь>, <Режим>)
Функция возвращает
True
, если проверка прошла успешно, или
False
— в противном слу- чае. В параметре
<Режим>
могут быть указаны следующие константы, определяющие тип проверки:
Глава 16. Работа с файлами и каталогами
307
os.F_OK
— проверка наличия пути или файла:
>>> import os # Подключаем модуль os
>>> os.access(r"file.txt", os.F_OK) # Файл существует
True
>>> os.access(r"C:\book", os.F_OK) # Каталог существует
True
>>> os.access(r"C:\book2", os.F_OK) # Каталог не существует
False
os.R_OK
— проверка на возможность чтения файла или каталога;
os.W_OK
— проверка на возможность записи в файл или каталог;
os.X_OK
— определение, является ли файл или каталог выполняемым.
Чтобы изменить права доступа из программы, необходимо воспользоваться функцией chmod()
из модуля os
. Функция имеет следующий формат: chmod(<Путь>, <Права доступа>)
Права доступа задаются в виде числа, перед которым следует указать комбинацию симво- лов
0o
(это соответствует восьмеричной записи числа):
>>> os.chmod(r"file.txt", 0o777) # Полный доступ к файлу
Вместо числа можно указать комбинацию констант из модуля stat
. За дополнительной информацией обращайтесь к документации по модулю.
16.6. Функции для манипулирования файлами
Для копирования и перемещения файлов предназначены следующие функции из модуля shutil
:
copyfile(<Копируемый файл>, <Куда копируем>)
— позволяет скопировать содержимое файла в другой файл. Никакие метаданные (например, права доступа) не копируются.
Если файл существует, он будет перезаписан. Если файл не удалось скопировать, возбу- ждается исключение
OSError или одно из исключений, являющихся подклассом этого класса. В качестве результата возвращается путь файла, куда были скопированы данные:
>>> import shutil # Подключаем модуль
>>> shutil.copyfile(r"file.txt", r"file2.txt")
>>> # Путь не существует:
>>> shutil.copyfile(r"file.txt", r"C:\book2\file2.txt")
... Фрагмент опущен ...
FileNotFoundError: [Errno 2] No such file or directory:
'C:\\book2\\file2.txt'
Исключение
FileNotFoundError является подклассом класса
OSError и возбуждается, если указанный файл не найден. Более подробно классы исключений, возбуждаемых при файловых операциях, мы рассмотрим в конце этой главы;
copy(<Копируемый файл>, <Куда копируем>)
— позволяет скопировать файл вместе с правами доступа. Если файл существует, он будет перезаписан. Если файл не удалось скопировать, возбуждается исключение
OSError или одно из исключений, являющихся подклассом этого класса. В качестве результата возвращает путь скопированного файла:
>>> shutil.copy(r"file.txt", r"file3.txt")