Выбрать главу

В стандартной библиотеке имеется библиотека 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 — с помощью разной функциональности.

Таблица 9.1. Работа с сетью
Библиотека Лицензия Причины использовать
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 в качестве моментально готовой к использованию системы-брокера сообщений