ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов
Скачать 7.92 Mb.
|
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") 308 Часть I. Основы языка Python copy2(<Копируемый файл>, <Куда копируем>) — позволяет скопировать файл вместе с метаданными. Если файл существует, он будет перезаписан. Если файл не удалось скопировать, возбуждается исключение OSError или одно из исключений, являющихся подклассом этого класса. В качестве результата возвращает путь скопированного файла: >>> shutil.copy2(r"file.txt", r"file4.txt") |