ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 866
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
316
Часть I. Основы языка Python
В один файл можно сохранить сразу несколько объектов, последовательно вызывая функ- цию dump()
. Вот пример сохранения нескольких объектов:
>>> obj1 = ["Строка", (2, 3)]
>>> obj2 = (1, 2)
>>> f = open(r"file.txt", "wb")
>>> pickle.dump(obj1, f) # Сохраняем первый объект
>>> pickle.dump(obj2, f) # Сохраняем второй объект
>>> f.close()
Для восстановления объектов необходимо несколько раз вызвать функцию load()
:
>>> f = open(r"file.txt", "rb")
>>> obj1 = pickle.load(f) # Восстанавливаем первый объект
>>> obj2 = pickle.load(f) # Восстанавливаем второй объект
>>> obj1, obj2
(['Строка', (2, 3)], (1, 2))
>>> f.close()
Сохранить объект в файл можно также с помощью метода dump(<Объект>)
класса
Pickler
Конструктор класса имеет следующий формат:
Pickler(<Файл>[, <Протокол>][, fix_imports=True])
Пример сохранения объекта в файл:
>>> f = open(r"file.txt", "wb")
>>> obj = ["Строка", (2, 3)]
>>> pkl = pickle.Pickler(f)
>>> pkl.dump(obj)
>>> f.close()
Восстановить объект из файла позволяет метод load()
из класса
Unpickler
. Формат конст- руктора класса:
Unpickler(<Файл>[, fix_imports=True][, encoding="ASCII"]
[, errors="strict"])
Пример восстановления объекта из файла:
>>> f = open(r"file.txt", "rb")
>>> obj = pickle.Unpickler(f).load()
>>> obj
['Строка', (2, 3)]
>>> f.close()
Модуль pickle позволяет также преобразовать объект в последовательность байтов и вос- становить объект из таковой. Для этого предназначены две функции:
dumps(<Объект>[, <Протокол>][, fix_imports=True])
— производит сериализацию объ- екта и возвращает последовательность байтов специального формата. Формат зависит от указанного протокола — числа от
0
до значения pickle.HIGHEST_PROTOCOL
в порядке от более старых к более новым и совершенным. По умолчанию в качестве номера про- токола используется значение: pickle.DEFAULT_PROTOCOL
(
3
).
Пример преобразования списка и кортежа:
>>> obj1 = [1, 2, 3, 4, 5] # Список
>>> obj2 = (6, 7, 8, 9, 10) # Кортеж
Глава 16. Работа с файлами и каталогами
317
>>> pickle.dumps(obj1) b'\x80\x03]q\x00(K\x01K\x02K\x03K\x04K\x05e.'
>>> pickle.dumps(obj2) b'\x80\x03(K\x06K\x07K\x08K\tK\ntq\x00.'
loads(<Последовательность байтов>[, fix_imports=True][, encoding="ASCII"][, errors="strict"])
— преобразует последовательность байтов специального формата в объект.
Пример восстановления списка и кортежа:
>>> pickle.loads(b'\x80\x03]q\x00(K\x01K\x02K\x03K\x04K\x05e.')
[1, 2, 3, 4, 5]
>>> pickle.loads(b'\x80\x03(K\x06K\x07K\x08K\tK\ntq\x00.')
(6, 7, 8, 9, 10)
Модуль shelve позволяет сохранять объекты под заданным строковым ключом и предос- тавляет интерфейс доступа, сходный со словарями, позволяя тем самым создать нечто, по- добное базе данных. Для сериализации объекта используются возможности модуля pickle
, а для записи получившейся строки по ключу в файл — модуль dbm
. Все эти действия модуль shelve производит самостоятельно.
Открыть файл с набором объектов поможет функция open()
. Функция имеет следующий формат: open(<Путь к файлу>[, flag="c"][, protocol=None][, writeback=False])
В необязательном параметре flag можно указать один из режимов открытия файла:
r
— только чтение;
w
— чтение и запись;
c
— чтение и запись (значение по умолчанию). Если файл не существует, он будет соз- дан;
n
— чтение и запись. Если файл не существует, он будет создан. Если файл существует, он будет перезаписан.
Функция open()
возвращает объект, с помощью которого производится дальнейшая работа с базой данных. Этот объект имеет следующие методы:
close()
— закрывает файл с базой данных. Для примера создадим файл и сохраним в нем список и кортеж:
>>> import shelve # Подключаем модуль
>>> db = shelve.open("db1") # Открываем файл
>>> db["obj1"] = [1, 2, 3, 4, 5] # Сохраняем список
>>> db["obj2"] = (6, 7, 8, 9, 10) # Сохраняем кортеж
>>> db["obj1"], db["obj2"] # Вывод значений
([1, 2, 3, 4, 5], (6, 7, 8, 9, 10))
>>> db.close() # Закрываем файл
keys()
— возвращает объект с ключами;
values()
— возвращает объект со значениями;
items()
— возвращает объект-итератор, который на каждой итерации генерирует кор- теж, содержащий ключ и значение:
318
Часть I. Основы языка Python
>>> db = shelve.open("db1")
>>> db.keys(), db.values()
(KeysView(
ValuesView(
>>> list(db.keys()), list(db.values())
(['obj1', 'obj2'], [[1, 2, 3, 4, 5], (6, 7, 8, 9, 10)])
>>> db.items()
ItemsView(
>>> list(db.items())
[('obj1', [1, 2, 3, 4, 5]), ('obj2', (6, 7, 8, 9, 10))]
>>> db.close()
get(<Ключ>[, <Значение по умолчанию>])
— если ключ присутствует, метод возвращает значение, соответствующее этому ключу. Если ключ отсутствует, возвращается значе- ние
None или значение, указанное во втором параметре;
setdefault(<Ключ>[, <Значение по умолчанию>])
— если ключ присутствует, метод воз- вращает значение, соответствующее этому ключу. Если ключ отсутствует, создается новый элемент со значением, указанным во втором параметре, и в качестве результата возвращается это значение. Если второй параметр не указан, значением нового элемента будет
None
;
pop(<Ключ>[, <Значение по умолчанию>])
— удаляет элемент с указанным ключом и возвращает его значение. Если ключ отсутствует, возвращается значение из второго параметра. Если ключ отсутствует, и второй параметр не указан, возбуждается исключе- ние
KeyError
;
popitem()
— удаляет произвольный элемент и возвращает кортеж из ключа и значения.
Если файл пустой, возбуждается исключение
KeyError
;
clear()
— удаляет все элементы. Метод ничего не возвращает в качестве значения;
update()
— добавляет элементы. Метод изменяет текущий объект и ничего не возвра- щает. Если элемент с указанным ключом уже присутствует, то его значение будет пере- записано. Форматы метода: update(<Ключ1>=<Значение1>[, ..., <КлючN>=<ЗначениеN>]) update(<Словарь>) update(<Список кортежей с двумя элементами>) update(<Список списков с двумя элементами>)
Помимо этих методов можно воспользоваться функцией len()
для получения количества элементов и оператором del для удаления определенного элемента, а также операторами in и not in для проверки существования или несуществования ключа:
>>> db = shelve.open("db1")
>>> len(db) # Количество элементов
2
>>> "obj1" in db
True
>>> del db["obj1"] # Удаление элемента
>>> "obj1" in db
False
>>> "obj1" not in db
True
>>> db.close()
Глава 16. Работа с файлами и каталогами
319 16.10. Функции для работы с каталогами
Для работы с каталогами используются следующие функции из модуля os
:
getcwd()
— возвращает текущий рабочий каталог. От значения, возвращаемого этой функцией, зависит преобразование относительного пути в абсолютный. Кроме того, важно помнить, что текущим рабочим каталогом будет каталог, из которого запускается файл, а не каталог с исполняемым файлом:
>>> import os
>>> os.getcwd() # Текущий рабочий каталог 'C:\\book'
chdir(<Имя каталога>)
— делает указанный каталог текущим:
>>> os.chdir("C:\\book\\folder1\\")
>>> os.getcwd() # Текущий рабочий каталог 'C:\\book\\folder1'
mkdir(<Имя каталога>[, <Права доступа>])
— создает новый каталог с правами досту- па, указанными во втором параметре. Права доступа задаются восьмеричным числом
(значение по умолчанию
0o777
). Пример создания нового каталога в текущем рабочем каталоге:
>>> os.mkdir("newfolder") # Создание каталога
rmdir(<Имя каталога>)
— удаляет пустой каталог. Если в каталоге есть файлы или ука- занный каталог не существует, возбуждается исключение — подкласс класса
OSError
Удалим каталог newfolder
:
>>> os.rmdir("newfolder") # Удаление каталога
listdir(<Путь>)
— возвращает список объектов в указанном каталоге:
>>> os.listdir("C:\\book\\folder1\\")
['file1.txt', 'file2.txt', 'file3.txt', 'folder1', 'folder2']
walk()
— позволяет обойти дерево каталогов. Формат функции: walk(<Начальный каталог>[, topdown=True][, onerror=None]
[, followlinks=False])
В качестве значения функция walk()
возвращает объект. На каждой итерации через этот объект доступен кортеж из трех элементов: текущего каталога, списка каталогов и спи- ска файлов, находящихся в нем. Если произвести изменения в списке каталогов во время выполнения, это позволит изменить порядок обхода вложенных каталогов.
Необязательный параметр topdown задает последовательность обхода каталогов. Если в качестве значения указано
True
(значение по умолчанию), последовательность обхода будет такой:
>>> for (p, d, f) in os.walk("C:\\book\\folder1\\"): print(p)
C:\book\folder1\
C:\book\folder1\folder1_1
C:\book\folder1\folder1_1\folder1_1_1
C:\book\folder1\folder1_1\folder1_1_2
C:\book\folder1\folder1_2
320
Часть I. Основы языка Python
Если в параметре topdown указано значение
False
, последовательность обхода будет другой:
>>> for (p, d, f) in os.walk("C:\\book\\folder1\\", False): print(p)
C:\book\folder1\folder1_1\folder1_1_1
C:\book\folder1\folder1_1\folder1_1_2
C:\book\folder1\folder1_1
C:\book\folder1\folder1_2
C:\book\folder1\
Благодаря такой последовательности обхода каталогов можно удалить все вложенные файлы и каталоги. Это особенно важно при удалении каталога, т. к. функция rmdir()
по- зволяет удалить только пустой каталог.
Пример очистки дерева каталогов: import os for (p, d, f) in os.walk("C:\\book\\folder1\\", False): for file_name in f: # Удаляем все файлы os.remove(os.path.join(p, file_name)) for dir_name in d: # Удаляем все каталоги os.rmdir(os.path.join(p, dir_name))
В
НИМАНИЕ
!
Очень осторожно используйте этот код. Если в качестве первого параметра в функции walk()
указать корневой каталог диска, то все имеющиеся в нем файлы и каталоги будут удалены.
Удалить дерево каталогов позволяет также функция rmtree()
из модуля shutil
. Функ- ция имеет следующий формат: rmtree(<Путь>[, <Обработка ошибок>[, <Обработчик ошибок>]])
Если в параметре
<Обработка ошибок>
указано значение
True
, ошибки будут проигнори- рованы. Если указано значение
False
(значение по умолчанию), в третьем параметре можно задать ссылку на функцию, которая будет вызываться при возникновении исклю- чения.
Пример удаления дерева каталогов вместе с начальным каталогом: import shutil shutil.rmtree("C:\\book\\folder1\\")
normcase(<Каталог>)
— преобразует заданный к каталогу путь к виду, подходящему для использования в текущей операционной системе. В Windows преобразует все прямые слэши в обратные. Также во всех системах приводит все буквы пути к нижнему ре- гистру:
>>> from os.path import normcase
>>> normcase(r"c:/BoOk/fIlE.TxT")
'c:\\book\\file.txt'
Как вы уже знаете, функция listdir()
возвращает список объектов в указанном каталоге.
Проверить, на какой тип объекта ссылается элемент этого списка, можно с помощью сле- дующих функций из модуля os.path
:
Глава 16. Работа с файлами и каталогами
321
isdir(<Объект>)
— возвращает
True
, если объект является каталогом, и
False
— в про- тивном случае:
>>> import os.path
>>> os.path.isdir(r"C:\book\file.txt")
False
>>> os.path.isdir("C:\\book\\")
True
isfile(<Объект>)
— возвращает
True
, если объект является файлом, и
False
— в про- тивном случае:
>>> os.path.isfile(r"C:\book\file.txt")
True
>>> os.path.isfile("C:\\book\\")
False
islink(<Объект>)
— возвращает
True
, если объект является символической ссылкой, и
False
— в противном случае. Если символические ссылки не поддерживаются, функция возвращает
False
Функция listdir()
возвращает список всех объектов в указанном каталоге. Если необхо- димо ограничить список определенными критериями, следует воспользоваться функцией glob(<Путь>)
из модуля glob
. Функция glob()
позволяет указать в пути следующие специ- альные символы:
?
— любой одиночный символ;
*
— любое количество символов;
[<Символы>]
— позволяет указать символы, которые должны быть на этом месте в пути.
Можно задать символы или определить их диапазон через дефис.
В качестве значения функция возвращает список путей к объектам, совпадающим с шабло- ном. Вот пример использования функции glob()
:
>>> import os, glob
>>> os.listdir("C:\\book\\folder1\\")
['file.txt', 'file1.txt', 'file2.txt', 'folder1_1', 'folder1_2',
'index.html']
>>> glob.glob("C:\\book\\folder1\\*.txt")
['C:\\book\\folder1\\file.txt', 'C:\\book\\folder1\\file1.txt',
'C:\\book\\folder1\\file2.txt']
>>> glob.glob("C:\\book\\folder1\\*.html") # Абсолютный путь
['C:\\book\\folder1\\index.html']
>>> glob.glob("folder1/*.html") # Относительный путь
['folder1\\index.html']
>>> glob.glob("C:\\book\\folder1\\*[0-9].txt")
['C:\\book\\folder1\\file1.txt', 'C:\\book\\folder1\\file2.txt']
>>> glob.glob("C:\\book\\folder1\\*\\*.html")
['C:\\book\\folder1\\folder1_1\\index.html',
'C:\\book\\folder1\\folder1_2\\test.html']
Обратите внимание на последний пример. Специальные символы могут быть указаны не только в названии файла, но и в именах каталогов в пути. Это позволяет просматривать сра- зу несколько каталогов в поисках объектов, соответствующих шаблону.
322
Часть I. Основы языка Python
16.10.1. Функция scandir()
Начиная с Python 3.5, в модуле os появилась поддержка функции scandir()
— более быст- рого и развитого инструмента для просмотра содержимого каталогов. Формат функции: os.scandir(<Путь>)
<Путь>
можно указать как относительный, так и абсолютный. Если он не задан, будет ис- пользовано строковое значение
(точка), т. е. путь к текущему каталогу.
Функция scandir()
возвращает итератор, на каждом проходе возвращающий очередной элемент — файл или каталог, что присутствует по указанному пути. Этот файл или каталог представляется экземпляром класса
DirEntry
, определенного в том же модуле os
, который хранит всевозможные сведения о файле (каталоге).
Класс
DirEntry поддерживает атрибуты:
name
— возвращает имя файла (каталога);
path
— возвращает путь к файлу (каталогу), составленный из пути, что был указан в вы- зове функции scandir()
, и имени файла (каталога), хранящегося в свойстве name
Для примера выведем список путей всех файлов и каталогов, находящихся в текущем ката- логе (при вводе команд в Python Shell текущим станет каталог, где установлен Python):
>>> import os
>>> for entry in os.scandir(): print(entry.name)
.\DLLs
.\Doc
.\include
# Часть вывода пропущена
.\python.exe
.\python3.dll
.\vcruntime140.dll
Видно, что путь, возвращаемый свойством path
, составляется из пути, заданного в вызове функции scandir()
(в нашем случае это используемый по умолчанию путь
), и имени фай- ла (каталога). Теперь попробуем указать путь явно:
>>> for entry in os.scandir("c:\python36"): print(entry.path) c:\python36\DLLs c:\python36\Doc c:\python36\include
# Часть вывода пропущена c:\python36\python.exe c:\python36\python3.dll c:\python36\vcruntime140.dll
Помимо описанных ранее атрибутов, класс
DirEntry поддерживает следующие методы:
is_file(follow_symlinks=True)
— возвращает
True
, если текущий элемент — файл, и
False в противном случае. Если элемент представляет собой символическую ссылку, и для параметра follow_symlinks указано значение
True
(или если параметр вообще
Глава 16. Работа с файлами и каталогами
323 опущен), проверяется элемент, на который указывает эта символическая ссылка. Если же для параметра follow_symlinks задано значение
False
, всегда возвращается
False
;
is_dir(follow_symlinks=True)
— возвращает
True
, если текущий элемент — каталог, и
False в противном случае. Если элемент представляет собой символическую ссылку, и для параметра follow_symlinks указано значение
True
(или если параметр вообще опущен), проверяется элемент, на который указывает эта символическая ссылка. Если же для параметра follow_symlinks задано значение
False
, всегда возвращается
False
;
is_symlink()
— возвращает
True
, если текущий элемент — символическая ссылка, и
False в противном случае;
stat(follow_symlinks=True)
— возвращает объект stat_result
, хранящий сведения о файле (более подробно он был описан в разд. 16.6). Если элемент представляет собой символическую ссылку, и для параметра follow_symlinks указано значение
True
(или если параметр вообще опущен), возвращаются сведения об элементе, на который указы- вает эта символическая ссылка. Если же для параметра follow_symlinks задано значение
False
, возвращаются сведения о самой символической ссылке. В Windows атрибуты st_ino
, st_dev и st_nlink объекта stat_result
, возвращенного методом stat()
, всегда хранят
0
, и для получения их значений следует воспользоваться функцией stat()
из мо- дуля os
, описанной в разд. 16.6.
Рассмотрим пару примеров:
для начала выведем список всех каталогов, что находятся в каталоге, где установлен
Python, разделив их запятыми:
>>> for entry in os.scandir(): if entry.is_dir(): print(entry.name, end=", ")
DLLs, Doc, include, Lib, libs, Scripts, tcl, Tools,
выведем список всех DLL-файлов, хранящихся в каталоге Windows, без обработки сим- волических ссылок:
>>> for entry in os.scandir("c:\windows"): if entry.is_file(follow_symlinks=False) and entry.name.endswith(".dll"): print(entry.name, end=", ")
В Python 3.6 итератор, возвращаемый функцией scandir()
, получил поддержку протокола менеджеров контекста (см. разд. 16.2). Так что мы можем выполнить просмотр содержимо- го какого-либо пути следующим способом:
>>> with os.scandir() as it: for entry in it: print(entry.name)
В том же Python 3.6 для Windows появилась возможность указывать путь в вызове функции scandir()
в виде объекта bytes
. Однако нужно иметь в виду, что в таком случае значения атрибутов name и path класса
DirEntry также будут представлять собой объекты bytes
, а не строки:
>>> with os.scandir(b"c:\python36") as it: for entry in it: print(entry.name)
324
Часть I. Основы языка Python b'DLLs' b'Doc' b'include'
# Часть вывода пропущена b'python.exe' b'python3.dll' b'vcruntime140.dll'
16.11. Исключения, возбуждаемые файловыми операциями
В этой главе неоднократно говорилось, что функции и методы, осуществляющие файловые операции, при возникновении нештатных ситуаций возбуждают исключение класса
OSError или одно из исключений, являющихся его подклассами. Настало время познакомиться с ними.
Исключений-подклассов класса
OSError довольно много. Вот те из них, что затрагивают именно операции с файлами и каталогами:
BlockingIOError
— не удалось заблокировать объект (файл или поток ввода/вывода);
ConnectionError
— ошибка сетевого соединения. Может возникнуть при открытии фай- ла по сети. Является базовым классом для ряда других исключений более высокого уровня, описанных в документации по Python;
FileExistsError
— файл или каталог с заданным именем уже существуют;
FileNotFoundError
— файл или каталог с заданным именем не обнаружены;
InterruptedError
— файловая операция неожиданно прервана по какой-либо причине;
IsADirectoryError
— вместо пути к файлу указан путь к каталогу;
NotADirectoryError
— вместо пути к каталогу указан путь к файлу;
PermissionError
— отсутствуют права на доступ к указанному файлу или каталогу;
TimeoutError
— истекло время, отведенное системой на выполнение операции.
Вот пример кода, обрабатывающего некоторые из указанных исключений: try open("C:\temp\new\file.txt") except FileNotFoundError: print("Файл отсутствует") except IsADirectoryError: print("Это не файл, а каталог") except PermissionError: print("Отсутствуют права на доступ к файлу") except OSError: print("Неустановленная ошибка открытия файла")
ЧАСТЬ
II
Библиотека PyQt 5
Глава 17. Знакомство с PyQt 5
Глава 18. Управление окном приложения
Глава 19. Обработка сигналов и событий
Глава 20. Размещение компонентов в окнах
Глава 21. Основные компоненты
Глава 22. Списки и таблицы
Глава 23. Работа с базами данных
Глава 24. Работа с графикой
Глава 25. Графическая сцена
Глава 26. Диалоговые окна
Глава 27. Создание SDI- и MDI-приложений
Глава 28. Мультимедиа
Глава 29. Печать документов
Глава 30. Взаимодействие с Windows
Глава 31. Сохранение настроек приложений
Глава 32. Приложение «Судоку»
ГЛ А В А
17
Знакомство с PyQt 5
Итак, изучение основ языка Python закончено, и мы можем перейти к рассмотрению биб- лиотеки PyQt, позволяющей разрабатывать приложения с графическим интерфейсом. Пер- вые три главы второй части книги можно считать основными, поскольку в них описывают- ся базовые возможности библиотеки и методы, которые наследуют все компоненты, так что материал этих глав нужно знать обязательно. Остальные главы содержат дополнительный справочный материал. В сопровождающий книгу электронный архив (см. приложение) включен файл
PyQt.doc
, который содержит более 750 дополнительных листингов, пояс- няющих материал второй части книги, — что позволило уменьшить ее объем, поскольку с этими листингами страниц книги было бы вдвое больше, чем всех страниц ее второй части.
17.1. Установка PyQt 5
Библиотека PyQt 5 не входит в комплект поставки Python, и прежде чем начать изучение ее основ, необходимо установить эту библиотеку на компьютер.
В настоящее время установка библиотеки PyQt 5 выполняется исключительно просто. Для этого достаточно запустить командную строку и отдать в ней команду: pip3 install PyQt5
Утилита pip3, поставляемая в составе Python и предназначенная для установки дополни- тельных библиотек, самостоятельно загрузит последнюю версию PyQt 5 и установит ее по пути
<каталог, в котором установлен Python>\lib\site-packages\PyQt5
В
НИМАНИЕ
!
При установке PyQt таким способом устанавливаются только компоненты библиотеки, не- обходимые для запуска программ. Средства разработчика (такие как программа Designer) и дополнительные компоненты, в частности клиентские части серверных СУБД, должны быть установлены отдельно.
Чтобы проверить правильность установки, выведем версии PyQt и Qt:
>>> from PyQt5 import QtCore
>>> QtCore.PYQT_VERSION_STR
'5.9.2'
>>> QtCore.QT_VERSION_STR
'5.9.3'