Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Pickle support

Boost , Boost.Python Reference Manual , Chapter 8. Topics

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Pickle - это модуль Python для сериализации объектов, также известный как персистентность, маршаллинг или сплющивание.

Часто необходимо сохранить и восстановить содержимое объекта в файл. Одним из подходов к этой проблеме является написание пары функций, которые считывают и записывают данные из файла в специальном формате. Мощным альтернативным подходом является использование модуля маринования Python. Используя способность Python к интроспекции, модуль маринования рекурсивно преобразует почти произвольные объекты Python в поток байтов, которые могут быть записаны в файл.

Библиотека Boost Python поддерживает модуль маринования через интерфейс, как подробно описано в ссылке Python Library для маринования . Этот интерфейс включает в себя специальные методы _getinitargs__, _getstate__ и _setstate___, как описано ниже. Обратите внимание, что Boost.Python также полностью совместим с модулем Python cPickle.

На пользовательском уровне – рост. Интерфейс Python включает в себя три специальных метода:

__getinitargs__

Когда пример увеличения. Класс расширения Python маринован, пиклер тестирует, если экземпляр имеет метод _getinitargs__. Этот метод должен возвращать Python tuple (наиболее удобно использовать boost::python::tuple). Когда экземпляр восстанавливается разборщиком, содержимое этого кортежа используется в качестве аргументов для конструктора класса.

Если _getinitargs__ не определено, pickle.load вызовет конструктор (_init__) без аргументов; т.е. объект должен быть конструктивным по умолчанию.

__getstate__

Когда экземпляр Boost.Python класс расширения маринован, пиклер тестирует, если экземпляр имеет метод _getstate__. Этот метод должен возвращать объект Python, представляющий состояние экземпляра.

__setstate__

Когда экземпляр класса расширения Boost.Python восстанавливается антипиклером (pickle.load), он сначала конструируется с использованием результата _getinitargs___ в качестве аргументов (см. выше). Впоследствии тестировщик отсоединяется, если новый экземпляр имеет метод __setstate__. Если это так, то в качестве аргумента этот метод называется результатом _getstate__ (объект Python).

Три специальных способа, описанных выше, могут быть .def()'ed индивидуально пользователем. Однако Boost.Python обеспечивает простой в использовании высокоуровневый интерфейс через boost::python::pickle_suite Класс, который также обеспечивает согласованность: _getstate__ и _setstate__ должны быть определены как пары. Использование этого интерфейса показано на следующих примерах.

В python/test есть три файла, которые показывают, как обеспечить поддержку маринования.

Класс C++ в этом примере может быть полностью восстановлен путем передачи соответствующего аргумента конструктору. Следовательно, достаточно определить способ огуречного интерфейса _getinitargs__. Это делается следующим образом: Определение функции огурца C++:

struct world_pickle_suite : boost::python::pickle_suite
{
  static
  boost::python::tuple
  getinitargs(world const& w)
  {
      return boost::python::make_tuple(w.get_country());
  }
};

Установить привязку Python:

class_<world>("world", args<const std::string&>())
      // ...
      .def_pickle(world_pickle_suite())
      // ...

Класс C++ в этом примере содержит данные о членах, которые не могут быть восстановлены ни одним из конструкторов. Поэтому необходимо предоставить _getstate__/_setstate__ пару методов интерфейса пикселя:

Определение функций C++ pickle:

struct world_pickle_suite : boost::python::pickle_suite
  {
    static
    boost::python::tuple
    getinitargs(const world& w)
    {
      // ...
    }
    static
    boost::python::tuple
    getstate(const world& w)
    {
      // ...
    }
    static
    void
    setstate(world& w, boost::python::tuple state)
    {
      // ...
    }
  };

Установление привязки Python для всего набора:

class_<world>("world", args<const std::string&>())
    // ...
    .def_pickle(world_pickle_suite())
    // ...

Для простоты _dict__ не входит в результат _getstate__. Обычно это не рекомендуется, но допустимый подход, если предполагается, что объект _dict__ всегда будет пустым. Обратите внимание, что охранник, описанный ниже, улавливает случаи, когда это предположение нарушается.

Этот пример похож на pickle2.cpp. Однако объект _dict__ включен в результат _getstate__. Это требует немного больше кода, но неизбежно, если объект _dict__ не всегда пуст.

Протокол маринования, описанный выше, имеет важную ловушку, которую делает конечный пользователь Boost. Модуль расширения Python может не знать:

_getstate__ определено, и экземпляр _dict__ не пуст.

Автор класса расширений Boost.Python может предоставить метод _getstate___, не учитывая возможности того, что: * его класс используется в Python в качестве базового класса. Скорее всего, _dict__ экземпляров производного класса необходимо мариновать, чтобы правильно восстановить экземпляры. * пользователь добавляет элементы в экземпляр _dict__ напрямую. Опять же, _dict__ экземпляра должен быть замаринован.

Чтобы предупредить пользователя об этой неочевидной проблеме, предоставляется охранник. Если определен _getstate__ и экземпляр _dict__ не пуст, Boost.Python тестирует, если класс имеет атрибут _getstate_manages_dict__. Исключение делается, если этот атрибут не определен:

RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)

Чтобы решить эту проблему, сначала следует установить, что методы _getstate__ и _setstate__ правильно управляют экземплярами _dict__. Обратите внимание, что это можно сделать либо на уровне C++, либо на уровне Python. Наконец, охранник должен быть намеренно переопределен. Например, в C++ (от pickle3.cpp):

struct world_pickle_suite : boost::python::pickle_suite
{
  // ...
  static bool getstate_manages_dict() { return true; }
};

Альтернативно в Python:

import your_bpl_module
class your_class(your_bpl_module.your_class):
  __getstate_manages_dict__ = 1
  def __getstate__(self):
    # your code here
  def __setstate__(self, state):
    # your code here
  • В модулях расширения Boost.Python, обеспечивающих полную поддержку огурцов для всех классов, будут значительные накладные расходы. В целом, полная поддержка маринования должна быть реализована только для классов расширения, которые в конечном итоге будут маринованы.
  • Избегайте использования _getstate__, если экземпляр также можно реконструировать с помощью _getinitargs__. Это автоматически позволяет избежать описанной выше ловушки.
  • Если требуется _getstate__, верните объект Python _dict__.

Пример pickle4.cpp демонстрирует альтернативную технику для реализации поддержки маринованных огурцов. Сначала мы снимаем Boost. Python через функцию class_::enable_pickling() определяет только основные атрибуты, необходимые для маринования:

class_<world>("world", args<const std::string&>())
    // ...
    .enable_pickling()
    // ...

Это позволяет использовать стандартный интерфейс Python, описанный в документации Python. Путем «впрыскивания» метода _getinitargs__ в определение класса обертывания мы делаем все экземпляры сборными:

# import the wrapped world class
from pickle4_ext import world
# definition of __getinitargs__
def world_getinitargs(self):
  return (self.get_country(),)
# now inject __getinitargs__ (Python is a dynamic language!)
world.__getinitargs__ = world_getinitargs

См. также учебный раздел о введении дополнительных методов из Python.


PrevUpHomeNext

Статья Pickle support раздела Boost.Python Reference Manual Chapter 8. Topics может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 8. Topics ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 07:33:08/0.0078849792480469/0