Qu'est-ce que PyPy? Python plus rapide sans douleur

Python a acquis la réputation d'être puissant, flexible et facile à utiliser. Ces vertus ont conduit à son utilisation dans une variété énorme et croissante d'applications, de flux de travail et de domaines. Mais la conception du langage - sa nature interprétée, son dynamisme d'exécution - signifie que Python a toujours été un ordre de grandeur plus lent que les langages natifs de la machine comme C ou C ++.

Au fil des ans, les développeurs ont mis au point une variété de solutions de contournement pour les limitations de vitesse de Python. Par exemple, vous pouvez écrire des tâches gourmandes en performances en C et les encapsuler avec Python; de nombreuses bibliothèques d'apprentissage automatique font exactement cela. Ou vous pouvez utiliser Cython, un projet qui vous permet de saupoudrer du code Python avec des informations de type d'exécution qui lui permettent d'être compilé en C.

Mais les solutions de contournement ne sont jamais idéales. Ne serait-ce pas génial si nous pouvions simplement prendre un programme Python existant  tel quel et l'exécuter beaucoup plus rapidement? C'est exactement ce que PyPy vous permet de faire.

Vidéo associée: Utilisation du runtime PyPy pour Python

PyPy contre CPython

PyPy est un remplacement de l'interpréteur Python standard, CPython. Alors que CPython compile Python en bytecode intermédiaire qui est ensuite interprété par une machine virtuelle, PyPy utilise la compilation juste-à-temps (JIT) pour traduire le code Python en langage d'assemblage natif de la machine.

En fonction de la tâche exécutée, les gains de performances peuvent être spectaculaires. En moyenne, PyPy accélère Python d'environ 7,6 fois, certaines tâches étant accélérées 50 fois ou plus. L'interpréteur CPython n'effectue tout simplement pas les mêmes types d'optimisations que PyPy, et ne le fera probablement jamais, car ce n'est pas l'un de ses objectifs de conception.

La meilleure partie est que peu ou pas d'effort est requis de la part du développeur pour débloquer les gains fournis par PyPy. Remplacez simplement CPython par PyPy, et pour la plupart, vous avez terminé. Il y a quelques exceptions, décrites ci-dessous, mais l'objectif déclaré de PyPy est d'exécuter du code Python existant et non modifié et de lui fournir une augmentation de vitesse automatique.

PyPy prend actuellement en charge Python 2 et Python 3, par le biais de différentes incarnations du projet. En d'autres termes, vous devez télécharger différentes versions de PyPy en fonction de la version de Python que vous utiliserez. La branche Python 2 de PyPy existe depuis beaucoup plus longtemps, mais la version Python 3 a été mise à jour ces derniers temps. Il prend actuellement en charge à la fois Python 3.5 (qualité de production) et Python 3.6 (qualité bêta).

En plus de prendre en charge tout le langage Python de base, PyPy fonctionne avec la grande majorité des outils de l'écosystème Python, comme  pip pour l'empaquetage ou  virtualenv pour les environnements virtuels. La plupart des packages Python, même ceux avec des modules C, devraient fonctionner tels quels, bien qu'il y ait des limitations que nous aborderons ci-dessous.

Comment fonctionne PyPy

PyPy utilise des techniques d'optimisation trouvées dans d'autres compilateurs juste-à-temps pour les langages dynamiques. Il analyse les programmes Python en cours d'exécution pour déterminer les informations de type des objets au fur et à mesure qu'ils sont créés et utilisés dans les programmes, puis utilise ces informations de type comme guide pour accélérer les choses. Par exemple, si une fonction Python fonctionne avec seulement un ou deux types d'objets différents, PyPy génère du code machine pour gérer ces cas spécifiques.

Les optimisations de PyPy sont gérées automatiquement lors de l'exécution, vous n'avez donc généralement pas besoin de modifier ses performances. Un utilisateur avancé peut expérimenter les options de ligne de commande de PyPy pour générer un code plus rapide pour des cas particuliers, mais ce n'est que rarement nécessaire.

PyPy s'écarte également de la façon dont CPython gère certaines fonctions internes, mais tente de préserver les comportements compatibles. Par exemple, PyPy gère le garbage collection différemment de CPython. Tous les objets ne sont pas immédiatement collectés une fois qu'ils sont hors de portée, donc un programme Python s'exécutant sous PyPy peut afficher une empreinte mémoire plus importante que lorsqu'il s'exécute sous CPython. Mais vous pouvez toujours utiliser les contrôles de collecte des ordures de haut niveau de Python exposés par le gcmodule, tels que gc.enable(), gc.disable()et gc.collect().

Si vous voulez des informations sur le comportement JIT de PyPy lors de l'exécution, PyPy inclut un module,, pypyjitqui expose de nombreux hooks JIT à votre application Python. Si vous avez une fonction ou un module qui semble mal fonctionner avec le JIT, pypyjitvous permet d'obtenir des statistiques détaillées à ce sujet.

Un autre module __pypy__spécifique à PyPy,, expose d'autres fonctionnalités spécifiques à PyPy, ce qui peut être utile pour écrire des applications qui exploitent ces fonctionnalités. En raison du dynamisme d'exécution de Python, il est possible de construire des applications Python qui utilisent ces fonctionnalités lorsque PyPy est présent et les ignore quand ce n'est pas le cas.

Limitations de PyPy

Aussi magique que puisse paraître PyPy, ce n'est pas de la magie. PyPy a certaines limites qui réduisent ou empêchent son efficacité pour certains types de programmes. Hélas, PyPy n'est pas un remplacement complètement universel du runtime CPython d'origine.

PyPy fonctionne mieux avec les applications Python pures

PyPy a toujours fonctionné au mieux avec les applications Python «pures» - c'est-à-dire les applications écrites en Python et rien d'autre. Les packages Python qui s'interfacent avec les bibliothèques C, telles que NumPy, ne se sont pas aussi bien comportés en raison de la façon dont PyPy émule les interfaces binaires natives de CPython. 

Les développeurs de PyPy ont réduit ce problème et ont rendu PyPy plus compatible avec la majorité des packages Python qui dépendent des extensions C. Numpy, par exemple, fonctionne très bien avec PyPy maintenant. Mais si vous voulez une compatibilité maximale avec les extensions C, utilisez CPython.

PyPy fonctionne mieux avec les programmes plus longs

L'un des effets secondaires de la façon dont PyPy optimise les programmes Python est que les programmes plus longs bénéficient le plus de ses optimisations. Plus le programme s'exécute longtemps, plus PyPy peut collecter d'informations de type à l'exécution et plus il peut effectuer d'optimisations. Les scripts Python one-and-done ne bénéficieront pas de ce genre de chose. Les applications qui en bénéficient ont généralement des boucles qui s'exécutent pendant de longues périodes, ou s'exécutent en continu en arrière-plan, par exemple des frameworks Web.

PyPy ne fait pas de compilation à l'avance

PyPy  compile  le code Python, mais ce n'est pas  un compilateur  pour le code Python. En raison de la façon dont PyPy effectue ses optimisations et du dynamisme inhérent à Python, il n'y a aucun moyen d'émettre le code JITted résultant en tant que binaire autonome et de le réutiliser. Chaque programme doit être compilé pour chaque exécution. Si vous souhaitez compiler Python en un code plus rapide pouvant s'exécuter en tant qu'application autonome, utilisez Cython, Numba ou le projet Nuitka actuellement expérimental.