Towards a Boost Free PyTango Daresbury Laboratory Towards a Boost Free PyTango G.R. Mant (STFC, Daresbury, Warrington, Cheshire, United Kingdom) T.M. Coutinho, A. Götz, V. Michel (ESRF, Grenoble, France)
C++/Python bindings What are the choices SWIG - old style Daresbury Laboratory C++/Python bindings What are the choices SWIG - old style Boost.Python - as we already know Cython - very neat syntax close to Python SIP - used in the LIMA project pybind11 - Syntax similar to Boost.Python, compact implementation thanks to C++11. Why did we choose pybind11 to replace Boost?
Daresbury Laboratory Boost: Why change Boost is an enormously large and complex suite of utility libraries that works with almost every C++ compiler in existence. It uses arcane template tricks and workarounds. Now that C++11-compatible compilers are widely available it’s not necessary. < 200 commits in the last 5 years
Daresbury Laboratory The future is pybind11 pybind11’s syntax and initial API design was heavily influenced by Boost.Python pybind11 is a lightweight header-only with no dependencies and doesn’t require specific build tools Heavily optimized for binary size; fast compile time Support for C++11, C++14 and C++17 language features Support for NumPy without having to include NumPy headers Support for embedding Python interpreter
More on pybind11 Useful features for PyTango that come as standard: Daresbury Laboratory More on pybind11 Useful features for PyTango that come as standard: STL data types, overloaded functions, enumerations, callbacks, multiple inheritance, smart pointers, capturing lambdas. Still actively developed at: http://github.com/pybind/pybind11 http://pybind11.readthedocs.io/en/stable/index.html
Daresbury Laboratory PyTango with pybind11 In a conda environment with g++ version 4.8.5 and python 2.7.14 PyTango codebase compiles in 8min. _tango.so size with boost: 106M pybind11: 97M branch: pybind11 at https://github.com/tango-controls/pytango.git
Progress so far Client Server - attributes - scaler, array, images Daresbury Laboratory Progress so far Client - attributes - scaler, array, images - pipes (reading) - commands - sync - async no callback - events Server
We are trying to keep the same API However, should we deprecate? Daresbury Laboratory We are trying to keep the same API However, should we deprecate? ApiUtil methods is_notifd_event_consumer_created & is_zmq_event_consumer_created ExtractAs: does anyone use anything other than numpy Async command with callback
DeviceProxy method overloading Daresbury Laboratory DeviceProxy method overloading .def("_get_property", [](Tango::DeviceProxy& self, string& prop_name) -> Tango::DbData { Tango::DbData dbData; self.get_property(prop_name, dbData); return dbData; }) .def("_get_property", [](Tango::DeviceProxy& self, std::vector<std::string>& prop_names) -> Tango::DbData self.get_property(prop_names, dbData);
DeviceProxy methods implemented, C++11 style, as lambda functions Daresbury Laboratory DeviceProxy methods implemented, C++11 style, as lambda functions .def("_read_attribute", [](Tango::DeviceProxy& self, std::string& attr_name, PyTango::ExtractAs extract_as=PyTango::ExtractAsNumpy) -> py::object { // the method body here }, py::arg("attr_name"), py::arg("extract_as")=PyTango::ExtractAsNumpy) .def("_read_attributes", [](Tango::DeviceProxy& self, std::vector<std::string> &attr_names, PyTango::ExtractAs extract_as=PyTango::ExtractAsNumpy) -> py::list { }, py::arg("attr_names"), py::arg("extract_as")=PyTango::ExtractAsNumpy)
dp = DeviceProxy('sys/tg_test/1') db_datum = DbDatum('test') Daresbury Laboratory dp = DeviceProxy('sys/tg_test/1') db_datum = DbDatum('test') db_datum.value_string = ['3.142'] dp.put_property(db_datum) props = dp.get_property('test') assert props.keys() == ["test"] assert props.values() == [['3.142']] db_datum = DbDatum('timeout') db_datum.value_string = ['0.05'] props = dp.get_property(['test', 'timeout']) assert props.keys() == ['test', 'timeout'] assert props.values() == [['3.142'], ['0.05']]
Reading/Writing attributes Daresbury Laboratory Reading/Writing attributes dp['long_scalar_w','double_spectrum', 'string_scalar', 'long_spectrum'] = 1234, [3.142, 6.284, 9.426], 'ESRF', np.array([1,2,3,4,5]) attr = dp['long_scalar_w','double_spectrum', 'string_scalar', 'long_spectrum'] assert attr[0].value == 1234 spectre = np.array([3.142, 6.284, 9.426]) assert set(attr[1].value) == set(spectre) assert attr[2].value == 'ESRF' spectre = np.array((1,2,3,4,5)) assert set(attr[3].value) == set(spectre)
Vincent Michel for his invaluable support and encouragement Daresbury Laboratory Thanks to: Vincent Michel for his invaluable support and encouragement Andy Gotz for giving me the opportunity to do this work and the Tango Consortium for financial support