Un serveur métier en Python / C++ 
Meet-up C++ 
02/10/2014 
Pierre Marquis & Alexandre Bonnasseau
Plan 
• Retour d’expérience 
• En pratique, quelques lignes de code
L'équipe dev carto 
Info 
trafic 
Itinéraire 
Plan 
Moteur de 
recherche 
géolocalisée 
Moteur de 
suggestion 
Géolocalisa...
Python WTF ??!
Python WTF ??! 
- Simplicité de code 
- Framework web léger 
- Richesse des modules 
- Facilité d'industrialisation
Notre philosophie 
- Python quand on peut 
- C++ quand c’est nécessaire
Chemin de l’équipe 
● Fonctions plus atomiques 
● Test U 
● Lint 
● Dojo 
● Pair programming 
● Code review
Schéma d’archi du plan
Chaîne d’industrialisation
Aujourd’hui 
+ 80% des serveurs migrés 
+ Langage très intéressant 
+ Framework mieux 
maîtrisé 
+ Dev plus rapide 
+ Plus...
En pratique : 
appeler du C++ depuis Python
Cadre 
– Existence d’une base de code C++ fiable et testée 
– On souhaite prototyper rapidement (besoin mouvant) 
– Besoin...
L'existant 
#define _USE_MATH_DEFINES 
#include <cmath> 
#include "geo.hpp" 
#include <sstream> 
#include <stdexcept> 
str...
Objectif 
Utiliser les fonctions C++ en python : 
$ python 
Python 2.7.3 
>>> import geo 
>>> print geo.geocoord2string(5....
Un module python écrit en C++ 
D'après : https://docs.python.org/2/extending/extending.html 
geomodule.cpp 
#include "Pyth...
Avec Boost.Python ? 
geomudule.cpp 
#include <boost/python.hpp> 
#include <boost/python/module.hpp> 
#include "geo.hpp" 
u...
Avec Boost.Python, on peut 
– Exposer des fonctions C++ en Python 
– Exposer des classes C++ en Python 
– Choisir quelles ...
Packager une extension Python 
Le fichier setup.py s’occupe de la compilation : 
from distutils.core import setup, Extensi...
Focus : Gestion de la mémoire 
– Un code C++ qui conserve une référence sur 
un objet Python doit appeler la macro 
Py_INC...
Focus : Gestion des erreurs 
Le code suivant lève une exception C++ : 
import geo 
print geo.geocoord2string(181) 
Sans Bo...
Un serveur de distance géographiques 
geoserveur.py 
from bottle import route, run, template 
from geo import GeoPoint 
@r...
Une autre approche : Producteur / Consommateur 
– Le code python peut appeler des méthodes C++ à 
distance 
– Par exemple ...
Les difficultés en Python 
quand on vient du C++
Typage dynamique 
– En C++ le typage statique offre une première 
validation du code 
– En Python, on ne détecte les erreu...
Threads 
– Le Global Interpreter Lock (GIL) assure que les traitements 
concurrents ne se marchent pas dessus : 
https://d...
Mémoire partagée 
– Le module mmap (Memory-mapped file) permet de partager de 
la mémoire entre plusieurs process 
– On pe...
Conclusion
Où va Mappy ? 
– Amélioration continue de l’outillage 
– Nouveaux services asynchrones en Python 
– … Et bientôt un nouvea...
Merci 
Enjoy : http://fr.mappy.com/ 
Pierre Marquis : pierre.marquis@mappy.com 
Alexandre Bonnasseau : https://github.com/...
Prochain SlideShare
Chargement dans…5
×

Comment développer un serveur métier en python/C++

555 vues

Publié le

Quelles sont les problématiques d'interfaçage, les avantages/inconvénients des langages, la stratégie de code, etc. dans le développement d'un serveur métier ?

Publié dans : Logiciels
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
555
Sur SlideShare
0
Issues des intégrations
0
Intégrations
4
Actions
Partages
0
Téléchargements
10
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Comment développer un serveur métier en python/C++

  1. 1. Un serveur métier en Python / C++ Meet-up C++ 02/10/2014 Pierre Marquis & Alexandre Bonnasseau
  2. 2. Plan • Retour d’expérience • En pratique, quelques lignes de code
  3. 3. L'équipe dev carto Info trafic Itinéraire Plan Moteur de recherche géolocalisée Moteur de suggestion Géolocalisation Itinéraire transports en commun
  4. 4. Python WTF ??!
  5. 5. Python WTF ??! - Simplicité de code - Framework web léger - Richesse des modules - Facilité d'industrialisation
  6. 6. Notre philosophie - Python quand on peut - C++ quand c’est nécessaire
  7. 7. Chemin de l’équipe ● Fonctions plus atomiques ● Test U ● Lint ● Dojo ● Pair programming ● Code review
  8. 8. Schéma d’archi du plan
  9. 9. Chaîne d’industrialisation
  10. 10. Aujourd’hui + 80% des serveurs migrés + Langage très intéressant + Framework mieux maîtrisé + Dev plus rapide + Plus d’agilité - Moins de maîtrise C++ - Multithread - Débogage binding
  11. 11. En pratique : appeler du C++ depuis Python
  12. 12. Cadre – Existence d’une base de code C++ fiable et testée – On souhaite prototyper rapidement (besoin mouvant) – Besoin d’exécution rapide pour des fonctions critiques
  13. 13. L'existant #define _USE_MATH_DEFINES #include <cmath> #include "geo.hpp" #include <sstream> #include <stdexcept> string geocoord2string(double angle) { if ( (angle > 180) || (angle < -180) ) throw invalid_argument("Invalid argument : angle must be beetween -180° and 180°"); int deg = int(floor(angle)); double rest = angle - deg; int minute = int(floor( rest * 60)); rest = rest * 60 - minute; int second = int(floor( rest * 60)); ostringstream result; result << deg << "° " << minute << "' " << second <<"''"; return result.str(); } double deg2rad(double deg) { return (deg * M_PI / 180); } GeoPoint::GeoPoint(double lat, double lng) : lat(lat), lng(lng) {} double GeoPoint::distance(const GeoPoint &other) { double nDLat = deg2rad(other.lat - this->lat); double nDLon = deg2rad(other.lng - this->lng); double thisLatRad = deg2rad(this->lat); double otherLatRad = deg2rad(other.lat); double nA = pow ( sin(nDLat/2), 2 ) + cos(thisLatRad) * cos(otherLatRad) * pow ( sin(nDLon/2), 2 ); double nC = 2 * atan2( sqrt(nA), sqrt( 1 - nA )); double nD = EARTH_RADIUS * nC; return nD; // Return our calculated distance }
  14. 14. Objectif Utiliser les fonctions C++ en python : $ python Python 2.7.3 >>> import geo >>> print geo.geocoord2string(5.36) 5° 21’ 36‘’ Projet complet disponible sur github : https://github.com/Mappy/un-serveur-metier-en-python-cpp
  15. 15. Un module python écrit en C++ D'après : https://docs.python.org/2/extending/extending.html geomodule.cpp #include "Python.h" #include "geo.hpp" static PyObject * geocoord2string_py(PyObject *self, PyObject *args) { double angle = 0; if (!PyArg_ParseTuple(args, "d", &angle)) return NULL; string res = geocoord2string(angle); return Py_BuildValue("s", res.c_str()); } // La liste des fonctions qu'on expose en Python static PyMethodDef geoMethods[] = { { "geocoord2string", geocoord2string_py, METH_VARARGS, "Convert a latitude or a longitude as an angle in a string in the form : d° m' s''." }, { NULL, NULL, 0, NULL } /* Sentinel */ }; // La fonction initnomdumodule est appelée par l'interpréteur Python // à l'import du module PyMODINIT_FUNC initgeo(void) { (void) Py_InitModule("geo", geoMethods); }
  16. 16. Avec Boost.Python ? geomudule.cpp #include <boost/python.hpp> #include <boost/python/module.hpp> #include "geo.hpp" using namespace boost::python; BOOST_PYTHON_MODULE(geo) { def("geocoord2string", geocoord2string); class_<GeoPoint>("GeoPoint", init<double, double>()) .def("distance", &GeoPoint::distance) … C’est tout ! ; }
  17. 17. Avec Boost.Python, on peut – Exposer des fonctions C++ en Python – Exposer des classes C++ en Python – Choisir quelles méthodes exposer pour une classe – Utiliser Boost::optional pour gérer les paramètres optionnels
  18. 18. Packager une extension Python Le fichier setup.py s’occupe de la compilation : from distutils.core import setup, Extension geo_module = Extension('geo', include_dirs = ['/usr/local/include',], library_dirs = ['/usr/local/lib',], extra_compile_args=['-std=c++11'], sources = ['geomodule.cpp', 'geo.cpp']) setup (name = 'Geo', version = '1.0', description = 'A geo package from Mappy', author = 'LBS team', author_email = 'lbs@mappy.com', url = 'http://github.com/mappy', long_description = ‘A demo package with geo functions', ext_modules = [geo_module]) Installer avec : python setup.py install Ou packager : python setup.py bdist
  19. 19. Focus : Gestion de la mémoire – Un code C++ qui conserve une référence sur un objet Python doit appeler la macro Py_INCREF() pour s'assurer que l'objet ne sera pas détruit – Il faut appeler Py_DECREF() pour libérer l'objet
  20. 20. Focus : Gestion des erreurs Le code suivant lève une exception C++ : import geo print geo.geocoord2string(181) Sans Boost.Python : terminate called after throwing an instance of 'std::invalid_argument' what(): Invalid argument : angle must be beetween -180° and 180° Avec Boost.Python : Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Invalid argument : angle must be beetween -180° and 180° Boost.Python permet également d'affiner la gestion des erreurs en associant des erreurs spécifiques Python aux exceptions C++
  21. 21. Un serveur de distance géographiques geoserveur.py from bottle import route, run, template from geo import GeoPoint @route('/distance/<lat1:float>,<lng1:float>/<lat2:float>,<lng2:float>') def index(lat1, lng1, lat2, lng2): dep = GeoPoint(lat1, lng1) arr = GeoPoint(lat2, lng2) return template("Distance = {{distance}}", distance=dep.distance(arr)) run(host='localhost', port=8888) A lancer par : python geoserver.py Tester l’url : http://localhost:8888/distance/48.85,2.35/43.30,5.38
  22. 22. Une autre approche : Producteur / Consommateur – Le code python peut appeler des méthodes C++ à distance – Par exemple via un bus RabbitMQ ou bien des appels distants ZMQ – Au final, le code Python délègue l‘exécution des sections critiques à des workers C++
  23. 23. Les difficultés en Python quand on vient du C++
  24. 24. Typage dynamique – En C++ le typage statique offre une première validation du code – En Python, on ne détecte les erreurs de type qu'à l'exécution !  il faut exécuter le code pour le tester  les tests unitaires sont indispensables !
  25. 25. Threads – Le Global Interpreter Lock (GIL) assure que les traitements concurrents ne se marchent pas dessus : https://docs.python.org/2/glossary.html#term-global-interpreter-lock http://dabeaz.blogspot.fr/2010/01/python-gil-visualized.html – Les modules thread / threading – encapsulent les primitives système de thread – fournissent des primitives de synchronisation : verrous, sémaphores, etc. – ... Mais à aucun moment deux instructions peuvent être exécutées en même temps à cause du GIL !  Mieux vaut utiliser multiprocessing
  26. 26. Mémoire partagée – Le module mmap (Memory-mapped file) permet de partager de la mémoire entre plusieurs process – On peut accéder à cette mémoire comme un fichier en lecture / écriture – On accède à cette mémoire comme un tableau de char – Mais on ne peut pas utiliser de types complexes (listes, dictionnaires, objets définis sur mesures)  Pas aussi souple qu’en C++
  27. 27. Conclusion
  28. 28. Où va Mappy ? – Amélioration continue de l’outillage – Nouveaux services asynchrones en Python – … Et bientôt un nouveau serveur d'itinéraire en Python / C++ ?
  29. 29. Merci Enjoy : http://fr.mappy.com/ Pierre Marquis : pierre.marquis@mappy.com Alexandre Bonnasseau : https://github.com/abonnasseau

×