В стандартной библиотеке имеется библиотека xdrlib (https://docs.python.org/3/library/xdrlib.html), позволяющая упаковывать и распаковывать данные в формате External Data Representation (XDR) (https://en.wikipedia.org/wiki/External_Data_Representation) от компании Sun. Этот формат не зависит от операционной системы и протокола передачи данных. Он работает на гораздо более низком уровне, нежели предыдущие варианты, и просто выполняет конкатенацию упакованных байтов, поэтому и клиент, и сервер должны знать тип и порядок упаковки. Рассмотрим пример сервера, получающего данные в формате XDR:
Данные могут иметь произвольную длину, поэтому мы добавили в начало файла упакованное беззнаковое число (4 байта), содержащее размер сообщения.
Мы должны знать заранее, что получаем данные типа unsigned int.
В этой строке считываем остальную часть сообщения…
…а в этой сбрасываем распаковщик, чтобы он начал работать с новыми данными.
Мы должны знать заранее, что получаем одну строку, а затем одно число с плавающей точкой.
Конечно, если обе стороны являлись программами Python, вы бы использовали Pickles. Но если сервер написан на каком-то другом языке, то соответствующий код клиента, отправляющего данные, выглядел бы так:
Сначала упакуем все данные, подлежащие отправке.
Далее отдельно упакуем длину сообщения…
…и добавим ее ко всему сообщению.
Сжатие
Стандартная библиотека Python поддерживает сжатие и декомпрессию данных с использованием алгоритмов zlib, gzip, bzip2 и lzma, а также создание архивов ZIP и TAR. Для того чтобы поместить в ZIP-архив данные, сериализованные с помощью Pickle, сделайте следующее:
import pickle
import gzip
data = "my very big object"
# Для запаковки и сериализации:
with gzip.open('spam.zip', 'wb') as my_zip:
····pickle.dump(data, my_zip)
# Для распаковки и десериализации:
with gzip.open('spam.zip', 'rb') as my_zip:
····unpickled_data = pickle.load(my_zip)
Протокол буфера
Элай Бендерски (Eli Bendersky), один из основных разработчиков Python, написал статью, посвященную вопросу снижения количества копий одних и тех же данных, хранящихся в памяти, с помощью буферов памяти (http://tinyurl.com/bendersky-buffer-protocol). Используя этот прием, вы даже можете считать данные из файла или сокета и поместить их в существующий буфер. Для получения более подробной информации обратитесь к документации для буферов протоколов и PEP 3118 (https://docs.python.org/3/c-api/buffer.html), где предлагаются улучшения, которые были реализованы в Python 3 и обратно портированы для версий Python 2.6 и выше.
Распределенные системы
Распределенные вычислительные системы выполняют задачу сообща (вроде игр, чат-комнат в Интернете или расчетов Hadoop) путем передачи информации друг другу.
В этом разделе сначала показываются самые популярные библиотеки для выполнения распространенных задач, связанных с сетью, а далее рассматривается шифрование (эта тема неотрывно следует за темой работы с сетью).
Работа с сетью
В Python коммуникация для соединенных сетей зачастую обрабатывается с помощью асинхронных инструментов или потоков, что позволяет обойти ограничение в один поток, создаваемое глобальной блокировкой интерпретатора. Все библиотеки, перечисленные в табл. 9.1, решают одну и ту же проблему — обходят GIL — с помощью разной функциональности.
Библиотека | Лицензия | Причины использовать |
---|---|---|
asyncio | Лицензия PSF | Предоставляет асинхронный цикл событий для управления коммуникацией с помощью неблокирующих сокетов и очередей, а также сопрограммами, определяемыми пользователем. Содержит асинхронные сокеты и очереди |
gevent | Лицензия MIT | Тесно связана с libev — библиотекой для асинхронного ввода/вывода, написанной на С. Предоставляет быстрый сервер WSGI, созданный на основе сервера HTTP. Содержит полезный модуль gevent.monkey (http://www.gevent.org/gevent.monkey.html), который имеет функции корректировки для стандартной библиотеки, что позволяет применять сторонние модули, использующие блокирующие сокеты |
Twisted | Лицензия MIT | Предоставляет асинхронные реализации более новых протоколов, например GPS, Internet of Connected Products (IoCP), и протокола Memcached (https://memcached.org/). В ее цикл событий интегрированы разнообразные фреймворки, управляемые событиями вроде wxPython или GTK. Имеет встроенный сервер SSH и клиентские инструменты |
PyZMQ | Лицензии LGPL (ZMQ) и BSD (часть с Python) | Позволяет настроить неблокирующие очереди сообщений, использующие API, похожий на сокеты, а также взаимодействовать с ними. Предоставляет поведения сокетов (запрос/ответ, публикация/подписка и отправка/получение), которые поддерживают распределенные вычисления. Используйте эту библиотеку, если хотите создать собственную инфраструктуру для коммуникации; в ее имени содержится буква Q, но она не похожа на RabbitMQ — ее можно использовать для того, чтобы создать что-то вроде RabbitMQ или что-то, что имеет совершенно другое поведение (в зависимости от выбранных шаблонов сокетов) |
pika | Лицензия BSD | Предоставляет легковесный клиент AMQP (протокол коммуникации) для соединения с RabbitMQ или другими брокерами сообщений. Включает в себя адаптеры, подходящие для использования в циклах событий Tornado или Twisted. Используйте ее вместе с брокером сообщений вроде RabbitMQ, если вам нужна более легковесная библиотека (без информационных панелей и других свистелок), которая позволяет отправлять содержимое внешнему брокеру сообщений вроде RabbitMQ |
Celery | Лицензия BSD | Предоставляет клиент AMQP для соединения с RabbitMQ или другими брокерами сообщений. Дает возможность сохранять состояния задач в бэкенде, который может использовать другие популярные варианты вроде соединения с базой данных с помощью SQLAlchemy, Memcached или другим способом. Имеет необязательный к использованию инструмент для веб-администрирования и наблюдения, который называется Flower. Может быть использована вместе с брокером сообщений вроде RabbitMQ в качестве моментально готовой к использованию системы-брокера сообщений |