Программирование на Python 3. Руководство издательство СимволПлюс
![]()
|
261 каталоги, – с помощью функции os.removedirs(). Файлы или каталоги могут удаляться с помощью функции os.remove(), а переименовывать ся с помощью функции os.rename(). Функция os.walk() позволяет выполнять итерации по всему дереву ка талогов, по очереди извлекая все имена файлов и каталогов. Кроме того, модуль os содержит множество низкоуровневых, платфор мозависимых функций, например, для работы с дескрипторами фай лов, а также для ветвления (только в системах UNIX), порождения до черних процессов и для запуска процессов. Модуль os предоставляет функции для взаимодействия с операцион ной системой, в частности, для работы с файловой системой, а модуль os.path содержит набор функций для работы со строками (путями к файлам) и некоторые вспомогательные функции для работы с файло вой системой. Функция os.path.abspath() возвращает абсолютный путь для своего аргумента, с удалением избыточных разделителей имен ка талогов и элементов ... Функция os.path.split() возвращает кортеж, содержащий 2 элемента, первый элемент которого содержит путь, а второй – имя файла (который будет представлен пустой строкой, ес ли имя файла в указанном пути не задано). Эти две части могут быть получены по отдельности, с помощью функций os.path.dirname() и os.path.basename() соответственно. Имя файла также может быть раз бито на две части – имя и расширение, с помощью функции os.path.splittext() . Функция os.path.join() принимает произвольное число строк путей и возвращает единый путь, используя платформоза висимый разделитель каталогов. Если в программе потребуется получить комплекс сведений о файле или каталоге, можно использовать функцию os.stat(), но когда необ ходимы только отдельные элементы информации, можно использовать соответствующие функции из модуля os.path, например, os.path.ex ists() , os.path.getsize(), os.path.isfile() или os.path.isdir(). Модуль mimetypes включает функцию mimetypes.guess_type(), которая пытается определить тип MIME файла. Пример: модули os и os.path Ниже показано, как можно использовать модули os и os.path для соз дания словаря, каждый ключ которого представляет собой имя файла (включая его путь), а значение – отметку времени (количество секунд, прошедших от начала эпохи), когда произошло последнее изменение файла, для всех файлов в каталоге path: date_from_name = {} for name in os.listdir(path): fullname = os.path.join(path, name) if os.path.isfile(fullname): date_from_name[fullname] = os.path.getmtime(fullname) 262 Глава 5. Модули Этот фрагмент программного кода выглядит очень понятным, но он может использоваться для составления перечня файлов только в од ном каталоге. Если необходимо выполнить обход всего дерева катало гов, можно воспользоваться функцией os.walk(). Ниже приводится фрагмент программы finddup.py. 1 Программный код создает словарь, каждый ключ которого представляет собой кор теж из двух элементов (размер файла и имя файла), где имя файла не содержит пути к нему. Каждое значение словаря – это список полных имен файлов, соответствующих имени файла в ключе и имеющих тот же размер: data = collections.defaultdict(list) for root, dirs, files in os.walk(path): for filename in files: fullname = os.path.join(root, filename) key = (os.path.getsize(fullname), filename) data[key].append(fullname) Для каждого каталога функция os.walk() возвращает путь к корнево му каталогу поддерева и два списка, один из них – это список подката логов в каталоге, а второй – список файлов в каталоге. Чтобы получить полный путь к файлу, необходимо объединить путь к корню и имя файла. Примечательно, что здесь не требуется выполнять рекурсию, так как функция os.walk() делает это сама. После сбора всей необходи мой информации можно выполнить обход получившегося словаря и вывести отчет о возможных дубликатах файлов: for size, filename in sorted(data): names = data[(size, filename)] if len(names) > 1: print("{0} ({1} bytes) may be duplicated " "({2} files):".format(filename, size, len(names))) for name in names: print("\t{0}".format(name)) Поскольку в качестве ключей словаря используются кортежи (размер и имя файла), нам не требуется использовать функцию key, чтобы от сортировать данные по размеру файла. Если какомулибо кортежу (размер, имя файла) соответствует более одного имени файла в списке, это могут быть дубликаты одного и того же файла. shell32.dll (8460288 bytes) may be duplicated (2 files): \windows\system32\shell32.dll \windows\system32\dllcache\shell32.dll 1 В главе 9 приводится более сложная версия программы поиска дубликатов файлов, findduplicatest.py, которая использует многопоточный режим ра боты и применяет вычисление контрольных сумм MD5. Обзор стандартной библиотеки языка Python 263 Это последний элемент из вывода, содержащего 3 282 строки, полу ченного командой finddup.py \windows в системе Windows XP. Работа с сетями и Интернетом Пакеты и модули для работы с сетями и Интернетом составляют ос новную часть стандартной библиотеки Python. На самом низком уров не модуль socket предоставляет наиболее фундаментальные функцио нальные возможности для работы с сетями, среди которых имеются функции создания сокетов, выполнения запросов к DNS (Domain Na me System – система доменных имен) и обработки IPадресов (internet Protocol – протокол Интернета). Настроить шифрование и аутентифи кацию при работе с сокетами можно с помощью модуля ssl. Модуль socketserver предоставляет реализации серверов TCP (Transmission Control Protocol – протокол управления передачей) и UDP (User Data gram Protocol – протокол пользовательских дейтаграмм). Эти серверы могут обрабатывать запросы непосредственно или создавать отдель ные процессы (за счет ветвления) и потоки управления для обработки каждого запроса. Асинхронная обработка сокетов на стороне клиентов и серверов может быть реализована с помощью модуля asyncore и по строенного на его основе более высокоуровневого модуля asynchat. В стандартной библиотеке Python имеется реализация WSGI (Web Ser ver Gateway Interface – интерфейс шлюза вебсервера), представляю щая собой стандартный интерфейс между вебсерверами и вебприло жениями, написанными на языке Python. В поддержку стандарта пакет wsgiref предоставляет рекомендации по внедрению WSGI и содержит модули для реализации серверов HTTP, совместимых с требованиями спецификаций WSGI, способных обрабатывать заголовки ответов и сценарии CGI (Common Gateway Interface – общий шлюзовой интер фейс). Кроме того, модуль http.server предоставляет реализацию сер вера HTTP, которому можно определить обработчик запросов (стан дартная реализация предоставляется) для запуска сценариев CGI. Мо дули http.cookies и http.cookiejar содержат функции для работы с cookies, а поддержка сценариев CGI предоставляется модулями cgi и cgitb. Доступ к запросам HTTP на стороне клиента может быть реализован с помощью модуля http.client, хотя более простой и удобный доступ к адресам URL обеспечивается модулями из пакета urllib: urllib.par se , urllib.request, urllib.response, urllib.error и urllib.robotparser. За грузка файлов из Интернета выполняется очень просто, как показано ниже: fh = urllib.request.urlopen("http://www.python.org/index.html") html = fh.read().decode("utf8") Функция urllib.request.urlopen() возвращает объект, который ведет себя практически как объект файла, открытый для чтения в двоичном 264 Глава 5. Модули режиме. Этот фрагмент получает файл index.html с вебсайта Python (в виде объекта bytes) и запоминает его в виде строки в переменной html . Имеется также возможность загружать файлы и сохранять их в локальной файловой системе с помощью функции urllib.request. urlretrieve() Имеется возможность производить синтаксический анализ докумен тов HTML и XHTML с помощью модуля html.parser; адреса URL могут анализироваться и создаваться с помощью модуля urllib.parse; а фай лы robots.txt могут анализироваться с помощью модуля urllib.robot parser . Данные в формате JSON (JavaScript Object Notation – формат записи объектов JavaScript) могут читаться и записываться с помо щью модуля json. Помимо поддержки серверов и клиентов HTTP в библиотеке имеется поддержка XMLRPC (Remote Procedure Call – вызов удаленных про цедур), реализованная в виде модулей xmlrpc.server и xmlrpc.client. Дополнительные возможности для работы на стороне клиента с прото колом FTP (File Transpotr Protocol – протокол передачи файлов) реа лизованы в виде модуля ftplib; для работы с протоколом NNTP (Net work News Transport Protocol – сетевой протокол передачи новостей) – в виде модуля nntplib; для работы с протоколом TELNET – в виде моду ля telnetlib. Модуль smtpd предоставляет реализацию сервера SMTP (Simple Mail Transport Protocol – упрощенный протокол электронной почты), мо дуль smtplib предоставляет возможность реализации клиентов элек тронной почты для протокола SMTP, модуль imaplib – для протокола IMAP4 (internet Message Access Protocol – протокол интерактивного доступа к электронной почте) и модуль poplib – для протокола POP3 (Post Office Protocol – протокол электронной почты). Возможность доступа к почтовым ящикам различных форматов обеспечивает мо дуль mailbox. Отдельные сообщения электронной почты (включая сооб щения, состоящие из нескольких частей) могут создаваться и обраба тываться средствами модуля email. Если возможностей пакетов и модулей стандартной библиотеки ока жется недостаточно, можно обратиться к Twisted (www.twistedmat rix.com ) – обширной библиотеке средств для работы с сетями, разраба тываемой сторонними разработчиками. Кроме того, существует мно жество сторонних библиотек, предназначенных для разработки веб приложений, включая Django (www.djangoproject.com) и Turbogears (www.turbogears.org), а также Plone (www.plone.org) и Zope (www.zo pe.org ), представляющих собой целые платформы для разработки сис тем управления содержимым. Все эти библиотеки написаны на языке Python. Обзор стандартной библиотеки языка Python 265 XML Для парсинга документов XML широко используются два основных подхода. Один из них основан на анализе DOM (Document Object Model – объектная модель документа), а другой – на использовании SAX (Sim ple API for XML – упрощенный прикладной интерфейс для работы с документами XML). В библиотеке имеется два парсера DOM – один из них представлен модулем xml.dom, а второй – модулем xml.dom.mini dom . Парсер SAX представлен модулем xml.sax. Мы уже использовали функцию xml.sax.saxutils.escape() из модуля xml.sax.saxutils (для эк ранирования служебных символов «&», «<» и «>»). Существует также функция xml.sax.saxutils.quoteattr(), которая выполняет то же дейст вие, но дополнительно экранирует кавычки (чтобы текст можно было использовать в атрибутах тегов); обратное преобразование можно вы полнить с помощью функции xml.sax.saxutils.unescape(). В библиотеке существует еще два парсера. Модуль xml.parsers.expat может использоваться для работы с документами XML с применением библиотеки expat, при наличии этой библиотеки в системе, и модуль xml.etree.ElementTree может использоваться для работы с документами XML через интерфейс словарей и списков. (По умолчанию парсеры DOM и дерева элементов за кулисами сами используют парсер, исполь зующий библиотеку expat.) Порядок создания документов XML вручную, с применением модулей DOM и деревьев элементов, и парсинг с использованием парсеров DOM, SAX и дерева элементов, описывается в главе 7. Пример: модуль xml.etree.ElementTree Парсеры DOM и SAX предоставляют прикладной программный интер фейс, которым пользуются опытные программисты, хорошо знающие формат XML, а модуль xml.etree.ElementTree предлагает более простой и более естественный для языка Python подход к парсингу и созданию документов XML. Модуль дерева элементов совсем недавно был добав лен в стандартную библиотеку 1 и потому может оказаться незнакомым для некоторых читателей. Поэтому мы представим здесь очень корот кий пример, чтобы можно было составить общее представление об этом модуле. В главе 7 будет представлен более сложный пример и про ведено сравнение программного кода, использующего парсеры DOM и SAX. Вебсайт организации NOAA (National Oceanic and Atmospheric Admi nistration – Национальное управление по исследованию океанов и ат мосферы) правительства США предоставляет самые разнообразные данные, включая файл в формате XML, в котором перечислены метео 1 Модуль xml.etree.ElementTree был включен в стандартную библиотеку в вер сии Python 2.5. 266 Глава 5. Модули рологические станции США. Файл насчитывает свыше 20 000 строк и содержит сведения примерно о двух тысячах метеорологических станций. Ниже приводится типичный пример одной из записей: Мы исключили несколько строк и уменьшили отступы. Размер файла составляет примерно 840 Кбайт, поэтому мы сжали его с помощью gzip до более приемлемого размера в 72 Кбайт. К сожалению, парсер на ос нове анализа элементов дерева требует либо имя файла, либо объект файла, но он не в состоянии работать со сжатыми файлами, так как с его точки зрения такие файлы являются набором случайных двоич ных данных. Решить эту проблему можно, выполнив следующие два действия: binary = gzip.open(filename).read() fh = io.StringIO(binary.decode("utf8")) Функция gzip.open() из модуля gzip напоминает встроен ную функцию open(), за исключением того, что она чита ет файлы, сжатые при помощи утилиты gzip (то есть с файлы с расширением .gz), просто как двоичные дан ные. Нам необходимо обеспечить доступность этих дан ных для парсера в виде файла, поэтому мы использовали метод bytes.decode() для преобразования двоичных дан ных в строку с кодировкой символов UTF8 (эта коди ровка по умолчанию используется для файлов XML) и создали объект io.StringIO, напоминающий файл, со строкой, вмещающей все содержимое файла XML. tree = xml.etree.ElementTree.ElementTree() root = tree.parse(fh) stations = [] for element in tree.getiterator("station_name"): stations.append(element.text) Здесь мы создали новый объект xml.etree.ElementTree.ElementTree и пе редали ему объект файла, откуда он будет читать содержимое файла XML, который нам требуется проанализировать. Парсер требует, что бы ему был передан объект файла, открытого для чтения, хотя в дейст вительности он читает его содержимое в строку объекта io.StringIO. Нам требуется извлечь из файла названия метеорологических стан ций, и это легко сделать с помощью метода xml.etree.ElementTree.Ele mentTree.getiterator() , который возвращает итератор, выполняющий итерации по всем объектам xml.etree.ElementTree.Element, имеющим Тип данных bytes , стр. 344 Тип данных io.String IO , стр. 249 Обзор стандартной библиотеки языка Python 267 тег с указанным именем. Чтобы извлечь текст, достаточно воспользо ваться атрибутом text элемента. Как и в случае с функцией os.walk(), нам не требуется предусматривать рекурсивную обработку – метод итератор сам сделает все необходимое. Если метод вызвать без имени тега, то с помощью полученного итератора можно будет выполнить об ход всех элементов документа XML. Прочие модули В книге недостаточно места, чтобы охватить почти 200 пакетов и мо дулей, входящих в состав стандартной библиотеки. Тем не менее это го краткого обзора вполне достаточно, чтобы получить представление о некоторых ключевых пакетах, применяемых в наиболее важных областях программирования. В последнем подразделе этого раздела мы рассмотрим еще несколько областей, представляющих для нас интерес. В предыдущем разделе мы видели, насколько просто создавать тесты в строках документирования и запускать их с помощью модуля doctest . В составе библиотеки имеется также платформа модульного тестирования, реализованная в виде модуля unittest, – это версия платформы тестирования JUnit языка Java, реализованная для языка Python. Кроме того, модуль doctest предоставляет некоторые возмож ности интеграции с модулем unittest. Помимо этого, существуют плат формы тестирования, созданные сторонними разработчиками, напри мер py.test (codespeak.net/py/dist/) и nose (www.somethingaboutoran ge.com/mrl/projects/nose/ ). Приложения, работающие в неинтерактивном режиме, такие как сер веры, часто сообщают о проблемах посредством записи сообщений в файлы журналов. Модуль logging предоставляет универсальный ин терфейс для записи сообщений в файлы журналов, а также он спосо бен отправлять сообщения с помощью запросов HTTP GET и POST, по средством сокетов или по электронной почте. В библиотеке имеется множество модулей, позволяющих выполнять интроспекцию и манипулирование программным кодом, и хотя их об суждение выходит далеко за рамки этой книги, тем не менее следует упомянуть о модуле pprint, который содержит функции форматиро ванного вывода объектов Python, включая коллекции, что иногда бы вает удобно при отладке. В главе 8 будет представлен простой пример использования модуля inspect, выполняющий интроспекцию сущест вующих объектов. Модуль threading предоставляет поддержку создания многопоточных приложений, а модуль queue реализует три различных типа очередей, которые могут безопасно использоваться в многопоточных приложе ниях. Тема управления несколькими потоками выполнения будет рас сматриваться в главе 8. 268 Глава 5. Модули В языке Python отсутствует встроенная поддержка создания приложе ний с графическим интерфейсом, тем не менее имеется несколько биб лиотек графического интерфейса, которые могут использоваться в про граммах на языке Python. Модуль tkinter обеспечивает доступ к биб лиотеке Tk, которая обычно устанавливается вместе с системой. Про граммирование графического интерфейса рассматривается в главе 13. Модуль abc (Abstract Base Class – базовый абстрактный класс) предоставляет функции, необходимые для созда ния базовых абстрактных классов. Этот модуль будет рассматриваться в главе 8. Модуль copy предоставляет функции copy.copy() и copy. deepcopy() , которые уже обсуждались в главе 3. Доступ к внешним функциям, то есть к функциям в разделяемых биб лиотеках (файлы .dll в Windows, .dylib – в Mac OS X и файлы .so – в Linux), обеспечивается модулем ctypes. В языке Python имеется так же поддержка C API, благодаря чему имеется возможность создавать нестандартные типы данных и функции на языке C и обеспечивать их доступность из программного кода на языке Python. Обсуждение мо дуля ctypes и поддержки C API выходит далеко за рамки этой книги. Если ни один из пакетов и модулей, упомянутых в этом разделе, не обеспечивает необходимые функциональные возможности, то прежде чем приступать к разработке собственных функций, ознакомьтесь с описанием глобального каталога модулей Python (Global Module In dex); возможно, там вы найдете подходящий модуль, поскольку здесь мы не в состоянии упомянуть все существующие модули. В случае не удачи попробуйте поискать нужный модуль в каталоге пакетов Python (Python Package Index – pypi.python.org/pypi), в котором содержится несколько тысяч расширений для Python – от маленьких модулей, со стоящих из единственного файла, и до огромных пакетов библиотек и платформ, насчитывающих сотни модулей. |