Программирование на Python 3. Руководство издательство СимволПлюс
![]()
|
Пример: модули calendar, datetime и time Объекты типа datetime.datetime обычно создаются программным спо собом, тогда как объекты, хранящие дату/время UTC, обычно получа ют информацию из внешних источников, таких как время создания файла. Ниже приводится несколько примеров: import calendar, datetime, time moon_datetime_a = datetime.datetime(1969, 7, 20, 20, 17, 40) moon_time = calendar.timegm(moon_datetime_a.utctimetuple()) moon_datetime_b = datetime.datetime.utcfromtimestamp(moon_time) moon_datetime_a.isoformat() # вернет: '19690720T20:17:40' moon_datetime_b.isoformat() # вернет: '19690720T20:17:40' time.strftime("%Y%m%dT%H:%M:%S", time.gmtime(moon_time)) Переменная moon_datetime_a является объектом типа datetime.datetime и хранит дату и время посадки корабля «Аполлон 11» на поверхность Луны. Переменная moon_time имеет тип int и хранит число секунд, про шедших от начала эпохи до момента посадки на Луну. Это число воз вращает функция calendar.timegm(), которая принимает объект типа time_struct , возвращаемый функцией datetime.datetime.utctimetuple(), и возвращает число секунд, которое представляет тип time_struct. 254 Глава 5. Модули (Поскольку посадка на Луну произошла до начала эпохи UNIX, число получится отрицательным.) Переменная moon_datetime_b является объ ектом типа datetime.datetime, и ее значение было получено из целочис ленной переменной moon_time, чтобы продемонстрировать возможность преобразования числа секунд, прошедших с начала эпохи в объект ти па datetime.datetime. 1 Последние три строки возвращают идентичные строки, содержащие дату/время в формате ISO 8601. Текущие дату/время UTC можно получить в виде объекта datetime.da tetime , вызвав функцию datetime.datetime.utcnow(), а в виде числа се кунд, прошедших с начала эпохи, – вызвав функцию time.time(). Для получения локальных даты/времени можно использовать datetime.da tetime.now() или time.mktime(time.localtime ()). Алгоритмы и типы коллекций Модуль bisect содержит функции поиска в отсортированных последо вательностях, таких как отсортированные списки, а также функции вставки элементов с сохранением порядка сортировки. Функции этого модуля используют алгоритм поиска методом половинного деления, поэтому они отличаются очень высокой скоростью работы. Модуль heapq содержит функции для преобразования последовательности, та кой как список, в «кучу» – разновидности коллекции, где первым эле ментом (в позиции с индексом 0) всегда является наименьший эле мент, и функции для добавления и удаления элементов, при которых последовательность остается кучей. Пакет collections содержит определения таких типов данных, как словарь collections.defaultdict и кортеж collections.namedtuple , которые уже рассматривались ра нее. Кроме того, в этом модуле объявляются типы дан ных collections.UserList и collections.UserDict, хотя на практике чаще используются встроенные подклассы ти пов list и dict, чем эти типы данных. Еще один тип дан ных – collections.deque – похож на список, но если спи сок обеспечивает очень быстрое добавление и удаление элементов в конце списка, то очереди collections.deque обеспечивают очень быстрое добавление и удаление эле ментов на обоих концах очереди – как в конце, так и в начале. В пакете collections также присутствуют определения нечисловых аб страктных классов Python (классы, которые могут наследоваться, но которые нельзя использовать непосредственно). Они будут обсуждать ся в главе 8. 1 К сожалению, в системе Windows функция datetime.datetime.utcfromtimes tamp() не может обрабатывать отрицательные отметки времени, то есть от метки времени, предшествующие дате 1 января 1970 года. Словари со значениями по умолча нию, стр. 161 Именованные кортежи, стр. 134 Обзор стандартной библиотеки языка Python 255 Модуль array содержит определение типа последовательности array.ar ray , способной хранить числа или символы весьма экономным спосо бом. Этот тип данных напоминает списки, за исключением того, что объекты этого типа могут хранить только элементы определенного ти па, который определяется на этапе его создания, поэтому, в отличие от списков, они не могут одновременно хранить объекты разных типов. Упоминавшийся ранее пакет NumPy также предоставляет эффективную реализацию массивов. Модуль weakref содержит средства создания слабых ссылок, которые ведут себя подобно обычным ссылкам на объекты, за исключением то го, что если единственная ссылка на объект – слабая ссылка, то такой объект может считаться готовым к утилизации. Это предотвращает со хранение объекта в памяти изза присутствия ссылки на него. Естест венно, имеется возможность проверить существование объекта, на ко торый указывает слабая ссылка, и при его наличии мы можем с помо щью этой ссылки обратиться к объекту. Пример: модуль heapq Модуль heapq содержит средства преобразования списка в кучу, а также для добавления элементов в кучу и удаления их из кучи, сохраняя по рядок следования элементов в списке, характерный для кучи. Куча – это двоичное дерево, обладающее свойствами кучи, когда первый эле мент (находящийся в позиции с индексом 0) является самым малень ким. 1 Каждое поддерево в куче также является кучей, поэтому любое поддерево тоже обладает всеми свойствами кучи. Ниже показано, как можно создать кучу с чистого листа: import heapq heap = [] heapq.heappush(heap, (5, "rest")) heapq.heappush(heap, (2, "work")) heapq.heappush(heap, (4, "study")) Если список уже существует, его можно преобразовать в кучу с помо щью функции heapq.heapify(alist), которая выполнит необходимое пе реупорядочивание элементов списка. Наименьший элемент может быть удален из кучи с помощью функции heapq.heappop(heap). for x in heapq.merge([1, 3, 5, 8], [2, 4, 7], [0, 1, 6, 8, 9]): print(x, end=" ") # выведет: 0 1 1 2 3 4 5 6 7 8 8 9 Функция heapq.merge() принимает произвольное число отсортирован ных итерируемых объектов в виде аргументов и возвращает итератор, позволяющий выполнить итерации по всем элементам всех итерируе мых объектов в порядке возрастания. 1 Строго говоря, модуль heapq реализует тип кучи min heap. Кучи, где первый элемент всегда является наибольшим, относятся к типу max heap. 256 Глава 5. Модули Форматы файлов, кодировки и сохранение данных Стандартная библиотека имеет обширную поддержку стандартных форматов файлов и кодировок. Модуль base64 содержит функции чтения и записи с использова нием кодировок Base16, Base32 и Base64 в соответствии с RFC 3548. 1 Модуль quopri содержит функции чтения и записи в формате «quotedprintable». 2 Этот формат оп ределяется документом RFC 1521 и используется для представления данных MIME (Multipurpose Internet Mail Extensions – многоцелевые расширения электронной поч ты Интернета). Модуль uu содержит функции чтения и за писи данных в формате uuencode. Документ RFC 1832 оп ределяет «External Data Representation Standard» (стан дарт представления внешних данных), а модуль xdrlib со держит функции чтения и записи данных в этом формате. Существуют также модули, предоставляющие возможность чтения и записи архивных файлов наиболее популярных форматов. Модуль bz2 обеспечивает возможность работы с файлами .bz2, модуль gzip обес печивает возможность работы с файлами .gz, модуль tarfile обеспечи вает возможность работы с файлами .tar, .tar.gz (а также .tgz) и .tar.bz2 и модуль zipfile обеспечивает возможность работы с файлами .zip. В этом подразделе мы увидим пример использования модуля tarfile, а немного ниже (на стр. 266) будет представлен небольшой пример, в котором используется модуль gzip. Еще раз с модулем gzip мы встре тимся в главе 7. Кроме того, стандартная библиотека обеспечивает поддержку некото рых форматов представления аудиоданных – например, модуль aifc реализует поддержку формата AIFF (Audio Interchange File Format – формат файлов для обмена аудиоданными) и модуль wave обеспечивает возможность для работы с файлами .wav (несжатыми). Некоторыми разновидностями аудиоданных можно манипулировать с помощью модуля audioop, а модуль sndhdr предоставляет пару функций, позво ляющих определить тип аудиоданных, хранящихся в файле, и некото рые характеристики этих данных, такие как частота дискретизации. Формат представления конфигурационных файлов (подобный форма ту файлов .ini в системе Windows) определяется документом RFC 822, 1 RFC (Request for Comments – запрос на комментарии и предложения) – это документы, используемые для определения различных интернеттехноло гий. Каждый документ имеет уникальный идентификационный номер, и многие из них со временем становятся официальными стандартами. 2 Способ 7битной кодировки, когда символы, не входящие в набор ASCII, преобразуются в их шестнадцатеричные коды, записанные латиницей. – Прим. перев. Кодировки символов, стр. 112 Обзор стандартной библиотеки языка Python 257 а модуль configparser предоставляет функции чтения и записи таких файлов. Многие приложения, такие как Excel, могут читать и писать данные в формате CSV (Comma Separated Value – значения, разделенные запя тыми) или в его разновидностях, таких как значения, разделенные символами табуляции. Модуль csv обеспечивает средства чтения и за писи этих форматов и в состоянии учитывать некоторые особенности, препятствующие возможности непосредственной обработки файлов CSV. В дополнение к поддержке различных форматов файлов стандартная библиотека содержит пакеты и модули, обеспечивающие средства со хранения данных. Модуль pickle используется для сохранения на дис ке и восстановления с диска произвольных объектов Python (включая целые коллекции) – подробнее об этом модуле рассказывается в гла ве 7. Помимо этого, стандартная библиотека поддерживает файлы DBM различных типов – эти файлы напоминают словари за исключе нием того, что их содержимое хранится на диске, а не в памяти, а их ключи и значения должны быть либо объектами типа bytes, либо строками. Модуль shelve, описываемый в главе 11, может использо ваться для работы с файлами DBM со строковыми ключами и произ вольными объектами Python в качестве значений – модуль незамет но для пользователя преобразует объекты Python в объекты типа bytes и обратно. Модули для работы с файлами DBM, прикладной программный интерфейс к базам данных и использование встроен ной базы данных SQLite рассматриваются в главе 11. Пример: модуль base64 Модуль base64 главным образом используется для обработки двоичных данных, внедренных в сообщения электронной почты в виде текста ASCII. Он также может использоваться для сохранения двоичных дан ных в файлах с расширением .py. Первый шаг состоит в том, чтобы преобразовать двоичные данные в формат Base64. В следующем фраг менте предполагается, что модуль base64 уже был импортирован, а путь к файлу .png хранится в переменной left_align_png: binary = open(left_align_png, "rb").read() ascii_text = "" for i, c in enumerate(base64.b64encode(binary)): if i and i % 68 == 0: ascii_text += "\\\n" ascii_text += chr(c) Этот фрагмент программного кода читает файл в режиме двоичного доступа и преобразует его в строку символов ASCII, в формате Base64. После каждого шестьдесят вось мого символа к строке добавляется комбинация символа обратного слеша и перевода строки. Это ограничивает left_align.png Тип данных bytes , стр. 344 258 Глава 5. Модули ширину строк 68 символами ASCII и гарантирует, что при обратном чтении данных символы перевода строки будут проигнорированы (по тому что символы обратного слеша экранируют их). Текст ASCII, по лученный таким способом, может сохраняться в виде литерала типа bytes в файле с расширением .py, например: LEFT_ALIGN_PNG = b"""\ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAA\ bmquu8PAmVT2+CwVV6rCyA9UfFMCkI+bN6p18tCWqcUzrDOwBh2zVCR+JZVeAAAAAElF\ TkSuQmCC""" Мы опустили большую часть строк, заместив их многоточием. Данные могут быть преобразованы обратно в первоначальный формат, как показано ниже: binary = base64.b64decode(LEFT_ALIGN_PNG) Двоичные данные могут быть записаны в файл с помощью цепочки вызовов: open(filename, "wb").write(binary). Двоичные данные в фай лах .py занимают значительно больше места, чем в оригинальной фор ме, но такая возможность может быть полезной, когда нам потребует ся написать программу, хранящую все необходимые двоичные данные в виде единственного файла .py. Пример: модуль tarfile В большинстве версий Windows отсутствует встроенная поддержка ра боты с форматом .tar, который очень широко используется в системах UNIX. Этот недостаток легко можно ликвидировать с помощью моду ля tarfile из стандартной библиотеки Python, который способен созда вать и распаковывать архивы .tar и .tar.gz (которые называют тарбол лами ), а при наличии дополнительных библиотек еще и архивы .tar.bz2 . Ниже приводятся ключевые выдержки из программы un tar.py , способной распаковывать тарболлы средствами модуля tarfile. Начинается программа с инструкций импортирования: BZ2_AVAILABLE = True try: import bz2 except ImportError: BZ2_AVAILABLE = False Модуль bz2 используется для работы с форматом сжатия bzip2, но опе рация импортирования будет терпеть неудачу, если интерпретатор Py thon был собран без доступа к библиотеке bzip2. (Версии Python для Windows всегда собираются со встроенной поддержкой сжатия bzip2, поэтому отсутствовать она может только в некоторых сборках для UNIX.) Здесь учитывается возможность того, что модуль может быть недоступен, именно поэтому используется блок try ... except и логи ческая переменная, к которой можно будет обратиться позже (хотя Обзор стандартной библиотеки языка Python 259 здесь мы не будем приводить программный код, который обращается к ней). UNTRUSTED_PREFIXES = tuple(["/", "\\"] + [c + ":" for c in string.ascii_letters]) Эта инструкция создает кортеж ('/', '\', 'A:', 'B:', ..., 'Z:', 'a:', 'b:', ..., 'z:') . Любое имя файла в тарболле, начинающееся с ука занных префиксов, считается подозрительным – в именах файлов в тарболле не должны использоваться абсолютные пути, поскольку это влечет за собой риск перезаписи системных файлов; поэтому в ка честве предварительной меры мы не будем распаковывать файлы, имена которых начинаются с указанных префиксов. def untar(archive): tar = None try: tar = tarfile.open(archive) for member in tar.getmembers(): if member.name.startswith(UNTRUSTED_PREFIXES): print("untrusted prefix, ignoring", member.name) elif ".." in member.name: print("suspect path, ignoring", member.name) else: tar.extract(member) print("unpacked", member.name) except (tarfile.TarError, EnvironmentError) as err: error(err) finally: if tar is not None: tar.close() Каждый файл в тарболле называется членом. Функция tarfile.getmem bers() возвращает список объектов tarfile.TarInfo, по одному для каж дого члена. Имена файлов членов, включая пути, хранятся в атрибуте tarfile.TarInfo.name . Если имя начинается с одного из подозрительных префиксов или содержит .. в пути, программа выводит сообщение об ошибке; в противном случае вызывается функция tarfile.extract(), сохраняющая член на диск. Модуль tarfile определяет множество соб ственных исключений, но в программе используется упрощенный подход к обработке ошибок, поэтому, когда возбуждается какоелибо исключение, она просто выводит текст сообщения об ошибке и завер шает работу. def error(message, exit_status=1): print(message) sys.exit(exit_status) Функция error() приведена здесь лишь для полноты картины. Функ ция main() (которая здесь не приводится) выводит сообщение о поряд ке использования, если программа была запущена с ключом – h или 260 Глава 5. Модули –– help ; в противном случае она выполняет некоторые основные провер ки, после чего вызывает функцию untar(), передавая ей имя файла тарболла. Работа с файлами, каталогами и процессами Модуль shutil предоставляет высокоуровневые функции для работы с файлами и каталогами, включая shutil.copy() и shutil.copytree(), по зволяющие копировать файлы и целые деревья каталогов; shutil.mo ve() , позволяющую перемещать деревья каталогов, и shutil.rmtree(), позволяющую удалять целые деревья каталогов, даже непустые. Временные файлы и каталоги должны создаваться с помощью модуля tempfile , который включает все необходимые для этого функции, на пример, tempfile.mkstemp(), и обеспечивает максимально возможную безопасность временных файлов. Модуль filecmp может использоваться для сравнения файлов – с помо щью функции filecmp.cmp() и целых каталогов – с помощью функции filecmp.cmpfiles() Одна из областей, где особенно эффективно могут использоваться про граммы на языке Python, – это управление ходом выполнения других программ. Реализовать такое управление можно средствами модуля subprocess , позволяющими запускать другие процессы, взаимодейст вовать с ними с помощью каналов и получать возвращаемые значения. Этот модуль описывается в главе 9. Существует более мощная альтер натива, в виде модуля multiprocessing, обладающего обширными воз можностями распределения работы между несколькими процессами и сбора результатов. Этот модуль нередко может использоваться как альтернатива многопоточной обработке данных. Модуль os обеспечивает платформонезависимый доступ к средствам операционной системы. Переменная os.environ хранит объект отобра жения, элементами которого являются имена переменных окружения и их значения. Рабочий каталог программы можно получить с помо щью функции os.getcwd(), а изменить его можно с помощью функции os.chdir() . Кроме того, модуль содержит функции для низкоуровневой работы с файлами на основе их дескрипторов. Функция os.access() мо жет использоваться для определения наличия файла или его доступ ности для чтения или записи. Функция os.listdir() возвращает спи сок записей (то есть имен файлов и каталогов, за исключением элемен тов . и ..) в указанном каталоге. Функция os.stat() возвращает раз личные сведения о файле или каталоге, такие как режим доступа, время последнего обращения и размер. Каталоги могут создаваться с помощью функции os.mkdir() или, если потребуется попутно создать промежуточные каталоги, с помощью функции os.makedirs(). Пустые каталоги могут удаляться с помощью функции os.rmdir(), а деревья каталогов, содержащие только пустые |