L’installation et la distribution de paquets Python (1/4)

Posté par  . Édité par Benoît Sibaud, alberic89 🐧, L'intendant zonard, nonas, palm123 et gUI. Modéré par Ysabeau 🧶 🧦. Licence CC By‑SA.
92
6
nov.
2023
Python

Quelques dépêches précédentes ont parlé des outils de packaging Python, comme ici, ou encore . Je vais chercher à faire un tour complet de la question, non seulement du point de vue de l’utilisateur qui cherche à comprendre quelle est « la bonne » solution (← ha ha ha rire moqueur…), mais aussi en expliquant les choix qui ont été faits, les évolutions, la structure de la communauté autour des outils, et les critiques qui leur sont souvent adressées, à tort ou à raison.

Sommaire

Il est question ici de packaging, terme pris dans un sens très large :

  • L’installation de paquets,
  • L’installation de Python lui-même,
  • L’administration d’environnements isolés,
  • La gestion de dépendances (lock files notamment),
  • La distribution de son code, en tant qu’auteur d’un paquet Python,
  • La compilation de code natif (écrit en C, C++, Rust…) pour être utilisé depuis Python.

Le langage Python, avec son écrasante popularité (premier au classement TIOBE), est vanté pour sa simplicité. Hélas, c’est devenu un lieu commun que cette simplicité ne s’étend pas aux outils de packaging, qui sont tout sauf faciles à maîtriser. Personnellement, j’y ai été confronté en voulant soulager la situation de Frescobaldi, une application écrite avec Python et PyQt. Frescobaldi possède une dépendance qui se trouve concentrer quelques difficultés de distribution et d’installation coriaces, en raison de code C++.

Ce problème d’ensemble a conduit à des évolutions rapides au cours des dernières années, qui tentent de garder un équilibre fragile entre l’introduction de nouvelles méthodes et la compatibilité avec l’existant. Parmi les utilisateurs, une confusion certaine a émergé avec cette cadence des changements, qui fait que des tutoriels écrits il y a quelques années voire quelques mois à peine sont complètement obsolètes, de même que des outils encore récemment recommandés.

Bien que de nombreux progrès soient indéniables, il existe un scepticisme très répandu concernant le degré de fragmentation déconcertant de l’écosystème, qui met l’utilisateur face à un labyrinthe d’outils qui se ressemblent.

Pour illustrer ce labyrinthe, voici une liste des outils que, personnellement, j’utilise ou j’ai utilisé, ou dont j’ai au moins lu sérieusement une partie de la documentation :

pip, pipx, virtualenv, venv, ensurepip, conda, condax, conda-lock, tox, build, twine, setuptools, setuptools-scm, flit, hatch, poetry, pdm, rye, pip-tools, maturin, setuptools-rust, meson-python, scikit-build, sip, pyinstaller, py2app, py2exe, cx_freeze, pyoxidizer, pynsist, briefcase, wheel, repairwheel, auditwheel, delocate, delvewheel, cibuildwheel

Encore une fois, je n’ai mis ceux que je connais. On en trouve encore d’autres ici.

Sans compter quelques outils dont j’ai connaissance mais qui sont aujourd’hui obsolètes ou non-maintenus :

distutils, distutils2, distribute, pyflow, bento, pipenv

Et quelques librairies de plus bas niveau : importlib.metadata, packaging, distlib, installer

Face à cette profusion, le classique aujourd’hui est de citer le XKCD qui va bien, et de renchérir en comparant au langage Rust, connu pour la simplicité de ses outils, à savoir :

cargo, rustup

Et c’est tout. Alors, pourquoi a-t-on besoin de plusieurs douzaines d’outils différents pour Python ?

Cela s’explique largement par des facteurs techniques, que j’expliquerai, qui font à la fois que le packaging Python est intrinsèquement plus compliqué, et qu’on lui demande beaucoup plus. En vérité, dans ces outils, on trouve des projets qui ont des cas d’utilisation complètement différents et ne s’adressent pas au même public (comme pip et repairwheel). Le hic, c’est qu’il y a, aussi, beaucoup de projets dont les fonctionnalités se recouvrent partiellement, voire totalement, comme entre pip et conda, entre venv et virtualenv, entre hatch et poetry, entre pyinstaller et briefcase, etc. Ces projets sont en concurrence et ont chacun leurs adeptes religieux et leurs détracteurs, à la manière des vieilles querelles Vim/Emacs et compagnie.

Cette dépêche est la première d’une série de quatre, qui ont pour but de décortiquer comment tout cela fonctionne, de retracer comment on en est arrivés là, et de parler des perspectives actuelles :

  1. L’histoire du packaging Python
  2. Tour de l’écosystème actuel
  3. Le casse-tête du code compilé
  4. La structure de la communauté en question

Les outils historiques : distutils et setuptools

Guido van Rossum a créé le langage Python en 1989. Rappelons qu’à l’époque, le World Wide Web n’existait pas encore, ni d’ailleurs le noyau Linux, les deux ayant été créés en 1991. D’après Wikipédia (source), le premier logiciel comparable aux gestionnaires de paquets actuels a été CPAN ­— destiné au langage Perl — qui ne date que de 1995. Python a donc grandi en même temps que l’idée des paquets, des gestionnaires de paquets et des dépôts sur Internet prenait racine.

C’est en 1998 (source) que le module distutils est né pour répondre au même besoin que CPAN pour Perl, dans le monde Python encore balbutiant. Ce module servait à compiler et installer des paquets, y compris des paquets écrits en C. Historiquement, il permettait aussi de générer des paquets au format RPM de Red Hat, et d’autres formats pour des machines de l’époque comme Solaris et HP-UX (source).

distutils faisait partie de la bibliothèque standard du langage. Il était configuré avec un fichier écrit en Python, nommé conventionnellement setup.py, qui prenait généralement cette forme :

from distutils.core import setup

setup(name='nom-paquet',
      version='x.y.z',
      ...)

On pouvait alors exécuter le setup.py comme un script, en lui passant le nom d’une commande :

$ python setup.py install # installe le paquet
$ python setup.py bdist_rpm # génère un RPM

Le téléchargement de paquets depuis un dépôt partagé ou la résolution des dépendances n’ont jamais fait partie des fonctions de distutils. De façon peut-être plus surprenante, distutils n’offre pas de moyen simple ou fiable pour désinstaller un paquet.

Le projet setuptools est arrivé en 2004 (source) pour pallier les limitations de distutils. Contrairement à distutils, setuptools a toujours été développé en dehors de la bibliothèque standard. Cependant, il était fortement couplé à distutils, le modifiant par des sous-classes… et par une bonne dose monkey-patching (source).

Lesdites limitations ont également conduit à un fork de distutils, nommé distutils2, démarré en 2010. Parmi les raisons citées par son initiateur figure le désir de faire évoluer distutils à un rythme plus soutenu que ce qui était raisonnable pour un module de la bibliothèque standard, surtout un module largement utilisé au travers de setuptools et son monkey-patching (source). Mais distutils2 a cessé d’être développé en 2012 (source).

De même, entre 2011 et 2013 (source), il a existé un fork de setuptools appelé distribute. Ses changements ont fini par être fusionnés dans setuptools.

Pour finir, distutils a été supprimé de la bibliothèque standard dans la version 3.12 de Python, sortie en octobre 2023, au profit de setuptools. Mais cela ne signifie pas que distutils n’est plus utilisé du tout : setuptools continue d’en contenir une copie qui peut être utilisée (bien que ce ne soit pas recommandé).

Il est aussi à noter que NumPy, la bibliothèque Python quasi universelle de calcul scientifique, maintient elle aussi son propre fork de distutils, numpy.distutils, qui est en train d’être remplacé (source). Cela montre à quel point le code de distutils s’est révélé à la fois essentiel, omniprésent à travers divers avatars ou forks, et difficile à faire évoluer.

La montée en puissance de pip et PyPI

Avec le développement d’Internet et la croissance de la communauté Python, il devenait nécessaire d’avoir un registre centralisé où pouvaient être déposés et téléchargés les paquets. C’est dans ce but qu’a été créé PyPI, le Python Package Index, en 2002 (source). (Ne pas confondre PyPI avec PyPy, une implémentation alternative de Python. PyPy se prononce « paille paille » alors que PyPI se prononce « paille pie aïe »).

distutils pouvait installer un paquet une fois le code source téléchargé, mais pas installer le paquet depuis PyPI directement, en résolvant les dépendances. Le premier outil à en être capable a été setuptools avec la commande easy_install (source), apparue en 2004.

Puis est arrivé pip en 2008. Entre autres, pip était capable, contrairement à tout ce qui existait jusque là, de désinstaller un paquet ! En quelques années, easy_install est devenu obsolète et pip s’est imposé comme l’outil d’installation standard. En 2013, la PEP 453 a ajouté à la bibliothèque standard un module ensurepip, qui bootstrape pip en une simple commande : python -m ensurepip. De cette manière, pip a pu continuer d’être développé indépendamment de Python tout en bénéficiant d’une installation facile (puisqu’on ne peut évidemment pas installer pip avec pip) et d’une reconnaissance officielle.

L’introduction du format « wheel »

Sans rentrer trop dans les détails à ce stade, le format principal pour distribuer un paquet jusqu’en 2012 était le code source dans une archive .tar.gz. Pour installer un paquet, pip devait décompresser l’archive et exécuter le script setup.py, utilisant setuptools. Bien sûr, cette exécution de code arbitraire posait un problème de fiabilité, car il était critique de contrôler l’environnement, par exemple la version de setuptools, au moment d’exécuter le setup.py.

setuptools avait bien un format de distribution précompilé, le format egg (le nom est une référence aux Monty Python). Un paquet en .egg pouvait être installé sans exécuter de setup.py. Malheureusement, ce format était mal standardisé et spécifique à setuptools. Il était conçu comme un format importable, c’est à dire que l’interpréteur pouvait directement lire l’archive (sans qu’elle soit décompressée) et exécuter le code dedans. C’était essentiellement une façon de regrouper tout le code en un seul fichier, mais il n’y avait pas vraiment d’intention de distribuer les .egg.

La PEP 427 a défini le format wheel pour que les paquets puissent être distribués sous forme précompilée sur PyPI, évitant l’exécution du setup.py durant l’installation.

Parmi les innovations, les fichiers wheels sont nommés d’après une convention qui indique avec quelle plateforme ils sont compatibles. Ceci a grandement facilité la distribution de modules Python codés en C ou C++. Jusqu’ici, ils étaient toujours compilés sur la machine de l’utilisateur, durant l’exécution du setup.py. Avec les wheels, il est devenu possible de distribuer le code déjà compilé, avec un wheel par système d’exploitation et par version de Python (voire moins, mais c’est pour la troisième dépêche).

Les débuts des environnements virtuels

Voici un problème très banal : vous voulez utiliser sur la même machine les projets foo et bar, or foo nécessite numpy version 3.14 alors que bar nécessite numpy version 2.71. Malheureusement, en Python, il n’est pas possible d’installer deux versions du même paquet à la fois dans un même environnement, alors que d’autres langages le permettent. (Plus précisément, il est possible d’installer deux versions en parallèle si elles ont des noms de module différents, le nom de module Python n’étant pas forcément le même que le nom de paquet, cf. Pillow qui s’installe avec pip install pillow mais s’importe avec import PIL. Mais tant que le module Python n’est pas renommé, les deux sont en conflit.)

La solution est alors de se servir d’un environnement virtuel, qui est un espace isolé où on peut installer des paquets indépendamment du reste du système. Cette technique a été développée dans le projet virtualenv, créé par Ian Bicking, qui est aussi l’auteur originel de pip. La première version date de 2007 (source).

Plus tard, en 2012 (source), un module venv a été ajouté à la bibliothèque standard. C’est une version réduite de virtualenv. On peut toutefois regretter que virtualenv soit encore nécessaire dans des cas avancés, ce qui fait que les deux sont utilisés aujourd’hui, même si venv est largement prédominant.

La création de la Python Packaging Authority (PyPA)

La première réaction naturelle en entendant le nom « Python Packaging Authority » est bien sûr de penser qu’à partir de 2012, date de sa création, ce groupe a été l’acteur d’une unification, d’une standardisation, d’une mise en commun des efforts, etc. par contraste avec la multiplication des forks de distutils.

Sauf que… le mot « Authority » était au départ une blague (sérieusement !). La preuve sur l’échange de mails où le nom a été choisi, les alternatives proposées allant de « ianb-ng » à « Ministry of Installation » (référence aux Monty Python), en passant par « Politburo ».

La Python Packaging Authority a démarré comme un groupe informel de successeurs à Ian Bicking (d’où le « ianb ») pour maintenir les outils qu’il avait créés, pip et virtualenv. Elle est un ensemble de projets, reconnus comme importants et maintenus.

Au fil du temps, la partie « Authority » son nom a évolué progressivement de la blague vers une autorité semi-sérieuse. La PyPA d’aujourd’hui développe des standards d’interopérabilité, proposés avec le même processus que les changements au langage Python lui-même, sous forme de PEP (Python Enhancement Proposals), des propositions qui ressemblent aux RFC, JEP et autres SRFI. La PyPA est également une organisation GitHub, sous l’égide de laquelle vivent les dépôts de divers projets liés au packaging, dont la plupart des outils que je mentionne dans cette dépêche, aux exceptions notables de conda, poetry et rye.

La PyPA n’est pas :

  • Un ensemble cohérent d’outils. Il y a beaucoup d’outils redondants (mais chacun ayant ses adeptes) dans la PyPA. Pour ne donner qu’un exemple, tout ce que peut faire flit, hatch peut le faire aussi.

  • Une véritable autorité. Elle reste composée de projets indépendants, avec chacun ses mainteneurs. Le fait qu’un standard soit accepté ne garantit pas formellement qu’il sera implémenté. J’ai lu quelque part une allusion à un exemple récent de « transgression » dans setuptools, mais je n’ai pas retrouvé de quel standard il s’agissait. Concrètement, cela ne veut pas dire que les transgressions sont fréquentes, mais plutôt qu’une PEP risque de ne pas être acceptée s’il n’est pas clair que les mainteneurs des outils concernés sont d’accord.

La décision finale sur une PEP est prise par un « délégué », et normalement, cette personne ne fait que formaliser le consensus atteint (même s’il peut y avoir des exceptions).

Il n’y a donc pas de place dans la PyPA actuelle pour des décisions du type de « flit devient officiellement déprécié au profit de hatch ».

Le développement d’un écosystème alternatif, conda et Anaconda

Pour compléter la liste de tout ce qui s’est passé en 2012, c’est aussi l’année de la première version de conda.

Cet outil a été créé pour pallier les graves lacunes des outils classiques concernant la distribution de paquets écrits en C ou C++ (Rust était un langage confidentiel à l’époque). Jusque là, on ne pouvait redistribuer que le code source, et il fallait que chaque paquet soit compilé sur la machine où il était installé.

Le format wheel introduit plus haut a commencé à résoudre ce problème, mais toutes ces nouveautés sont concomitantes.

Contrairement à tous les autres outils mentionnés dans cette dépêche, Conda, bien qu’open source, est développé par une entreprise (d’abord appelée Continuum Analytics, devenue Anaconda Inc.). C’est un univers parallèle à l’univers PyPA : un installeur de paquets différent (conda plutôt que pip), un format de paquet différent, un gestionnaire d’environnements virtuel différent (conda plutôt que virtualenv ou venv), une communauté largement séparée. Il est aussi beaucoup plus unifié.

conda adopte un modèle qui se rapproche davantage de celui d’une distribution Linux que de PyPI, en mettant le packaging dans les mains de mainteneurs séparés des auteurs des paquets. Il est possible de publier ses propres paquets indépendamment d’une organisation, mais ce n’est pas le cas le plus fréquent. On pourrait comparer cela à ArchLinux, avec son dépôt principal coordonné auquel s’ajoute un dépôt non coordonné, l’AUR.

Cette organisation permet à conda de faciliter énormément la distribution de modules C ou C++. En pratique, même avec les wheels, cela reste une source infernale de casse-têtes avec les outils PyPA (ce sera l’objet de la troisième dépêche), alors que tout devient beaucoup plus simple avec conda. Voilà son gros point fort et sa raison d’être.

Il faut bien distinguer conda, l’outil, d’Anaconda, qui est une distribution de Python contenant, bien sûr, conda, mais aussi une flopée de paquets scientifiques ultra-populaires comme NumPy, SciPy, matplotlib, etc. Anaconda est très largement utilisée dans le monde scientifique (analyse numérique, data science, intelligence artificielle, etc.). Il existe aussi Miniconda3, qui est une distribution plus minimale avec seulement conda et quelques autres paquets essentiels. Enfin, conda-forge est un projet communautaire (contrairement à Anaconda, développé au sein de l’entreprise Anaconda Inc.) qui distribue des milliers de paquets. On peut, dans une installation d’Anaconda, installer un paquet depuis conda-forge avec conda - c conda-forge (le plus courant), ou bien (moins courant) installer une distribution nommée « Miniforge », qui est un équivalent de Miniconda3 fondé entièrement sur conda-forge.

Les PEP 517 et 518, une petite révolution

S’il y a deux PEP qui ont vraiment changé le packaging, ce sont les PEP 517 et 518.

La PEP 518 constate le problème que le fichier de configuration de setuptools, le setup.py, est écrit en Python. Comme il faut setuptools pour exécuter ce fichier, il n’est pas possible pour lui, par exemple, de spécifier la version de setuptools dont il a besoin. Il n’est pas possible non plus d’avoir des dépendances dans le setup.py autres que setuptools (sauf avec un hack nommé setup_requires proposé par setuptools, qui joue alors un rôle d’installeur de paquets comme pip en plus de son rôle normal… ce pour quoi setuptools n’excellait pas). Elle décrit aussi explicitement comme un problème le fait qu’il n’y ait pas de moyen pour une alternative à setuptools de s’imposer. En effet, le projet setuptools souffrait, et souffre toujours gravement, d’une surcomplication liée à toutes ses fonctionnalités dépréciées.

Pour remédier à cela, la PEP 518 a introduit un nouveau fichier de configuration nommé pyproject.toml. Ce fichier est écrit en TOML, un format de fichier de configuration (comparable au YAML). C’est l’embryon d’un mouvement pour adopter une configuration qui soit déclarative plutôt qu’exécutable. Le TOML avait déjà été adopté par l’outil Cargo de Rust.

Le pyproject.toml contient une table build-system qui déclare quels paquets doivent être installés pour exécuter le setup.py. Elle se présente ainsi :

[build-system]
requires = ["setuptools>=61"]

Cet exemple pourrait être utilisé dans un projet dont le setup.py a besoin de setuptools version 61 au moins.

Mais ce n’est pas tout. La PEP 518 définit aussi une table tool avec des sous-tables arbitraires tool.nom-d-outil, qui permet à des outils arbitraires de lire des options de configuration, qu’ils soient des outils de packaging, des reformateurs de code, des linters, des générateurs de documentation,… pyproject.toml est donc devenu un fichier de configuration universel pour les projets Python. (Anecdote : au départ, il n’était pas prévu pour cela, mais il a commencé à être utilisé comme tel, si bien que la PEP 518 a été modifiée a posteriori pour structurer cela dans une table tool.)

La deuxième étape a été la PEP 517. Elle va plus loin, en standardisant une interface entre deux outils appelés build frontend et build backend. Le build frontend est l’outil appelé par l’utilisateur, par exemple pip, qui a besoin de compiler le paquet pour en faire un wheel installable (ou une sdist, soit une archive du code source avec quelques métadonnées, mais c’est un détail). Le build backend est un outil comme setuptools qui va créer le wheel.

Le rôle du build frontend est assez simple. Pour schématiser, il lit la valeur build-system.requires du pyproject.toml, installe cette liste de dépendances, puis lit la valeur build-system.build-backend, importe le build backend en Python, et appelle la fonction backend.build_wheel().

Voici un exemple de pyproject.toml utilisant les PEP 517 et 518 avec setuptools comme build backend :

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

Ainsi, il est devenu possible d’écrire et utiliser des build backends complètement différents de setuptools, sans même de fichier setup.py. L’un des premiers build backends alternatifs a été flit, qui cherche à être l’opposé de setuptools : le plus simple possible, avec le moins de configuration possible.

La PEP 517 décrit bien son objectif :

While distutils / setuptools have taken us a long way, they suffer from three serious problems : (a) they’re missing important features like usable build-time dependency declaration, autoconfiguration, and even basic ergonomic niceties like DRY-compliant version number management, and (b) extending them is difficult, so while there do exist various solutions to the above problems, they’re often quirky, fragile, and expensive to maintain, and yet (c) it’s very difficult to use anything else, because distutils/setuptools provide the standard interface for installing packages expected by both users and installation tools like pip.

Previous efforts (e.g. distutils2 or setuptools itself) have attempted to solve problems (a) and/or (b). This proposal aims to solve (c).

The goal of this PEP is get distutils-sig out of the business of being a gatekeeper for Python build systems. If you want to use distutils, great ; if you want to use something else, then that should be easy to do using standardized methods.

La PEP 621, un peu de standardisation

Suite aux PEP 518 et 517, plusieurs build backends alternatifs ont émergé. Bien sûr, tous les build backends avaient des manières différentes de spécifier les métadonnées du projet comme le nom, la version, la description, etc.

La PEP 621 a standardisé cette partie de la configuration, en définissant une nouvelle section du pyproject.toml, la table project. Concrètement, elle peut ressembler à :

[project]
name = "my-project"
version = "0.1"
description = "My project does awesome things."
requires-python = ">=3.8"
authors = [{name = "Me", email = "me@example.com"}]
...

En effet, écrire les métadonnées n’est pas la partie la plus intéressante d’un build backend. Les vraies différences se trouvent, par exemple, dans la prise en charge des extensions C ou C++, ou bien dans des options de configuration plus avancées. La PEP 621 permet de changer plus facilement de build backend en gardant l’essentiel de la configuration de base.

De plus, elle encourage la configuration statique, par opposition au setup.py de setuptools. L’avantage d’une configuration statique est sa fiabilité : aucune question ne se pose sur l’environnement d’exécution du setup.py, sa portabilité, etc.

Pour donner un exemple concret, on apprend dans cette section de la PEP 597 que les développeurs écrivaient souvent dans le setup.py un code qui lit le README avec l’encodage système au lieu de l’UTF-8, ce qui peut rendre le paquet impossible à installer sous Windows. C’est le genre de problèmes systémiques qui sont éliminés par la configuration statique.

Malgré tout, la configuration dynamique reste utile. C’est typiquement le cas pour la valeur de version, qui est avantageusement calculée en consultant le système de contrôle de version (par exemple avec git describe pour Git). Dans ces situations, on peut marquer la valeur comme étant calculée dynamiquement avec

[project]
dynamic = ["version"]

C’est alors au build backend de déterminer la valeur par tout moyen approprié (éventuellement configuré dans la table tool).

L’émergence d’outils tout-en-un alternatifs

Cet historique est très loin d’être exhaustif, et pourtant on sent déjà la prolifération d’outils différents. Face à la confusion qui en résulte, des développeurs ont tenté d’écrire des outils « tout-en-un » qui rassemblent à peu près toutes les fonctionnalités en une seule interface cohérente : installation, build frontend, build backend, gestion des environnements virtuels, installation d’une nouvelle version de Python, mise à jour d’un lock file, etc. Parmi eux, on peut notamment citer poetry, développé depuis 2018 (source), qui se distingue en ne participant pas à la PyPA et en réimplémentant bien plus de choses que d’autres (notamment en ayant son propre résolveur de dépendances distinct de celui de pip). On peut penser aussi à hatch, qui, lui, fait partie de la PyPA et ne fait pas autant de choses, mais s’intègre mieux à l’existant. Et pour mentionner le dernier-né, il y a également rye, qui cherche à modifier la façon dont Python est boostrapé, en utilisant exclusivement des Pythons gérés par lui-même, qui ne viennent pas du système, et en étant écrit lui-même en Rust plutôt qu’en Python.

Conclusion

J’espère que cet historique permet de mieux comprendre pourquoi le packaging est tel qu’il est aujourd’hui.

L’un des facteurs majeurs est l’omniprésence des extensions C, C++ ou maintenant Rust qui doivent être précompilées. C’est la raison essentielle pour laquelle conda et tout son écosystème existent et sont séparés du monde de la PyPA.

Un autre facteur est à chercher dans les problèmes de conception de distutils, un code qui date de l’époque des premiers gestionnaires de paquets et qui n’était pas prêt à accompagner Python pour vingt ans. C’est pour cela qu’il a été forké si souvent, et c’est pour en finir avec l’hégémonie de son fork setuptools que les PEP 518 et 517 ont volontairement ouvert le jeu aux outils alternatifs.

Il faut enfin voir que la PyPA n’a jamais été un groupe unifié autour d’un outil, et qu’il est difficile de changer de modèle social.

Dans la deuxième dépêche, je ferai un tour complet de l’état actuel, en présentant tous les outils et les liens entre eux.

  • # Excellente initiative !

    Posté par  . Évalué à 10.

    Super état des lieux ! J'ai hâte de lire la suite. Merci !

  • # merci et venv

    Posté par  (site web personnel, Mastodon) . Évalué à 4.

    J'ai toujours de la peine en usage des environnements virtuels.
    Entre la raison d'être et les bonnes pratiques pour s'y retrouver dans un projet installé il y a quelques temps, c'est la galère 😬

    Il y a quoi comme bonne ressource pour gérer les venv python?

    • [^] # Re: merci et venv

      Posté par  (site web personnel) . Évalué à 4.

      Bonjour,

      Honnêtement pour gérer quelques d'environnements virtuels avec plusieurs versions de python et pour ne pas me mélanger les pinceaux, le truc qui fait CRAC BOUM HUUUUE :

      Le fichier README

      Dans ce fichier je décris rapidement quel environnement python utiliser …

      Mais si vous avez mieux, je suis preneur

      • [^] # Re: merci et venv

        Posté par  . Évalué à 2.

        Mais si vous avez mieux, je suis preneur

        Docker

        • [^] # Re: merci et venv

          Posté par  . Évalué à 6.

          Pour ça aussi, il y a le XKCD qui va bien ☺

          • [^] # Re: merci et venv

            Posté par  . Évalué à 1.

            Quel est le rapport ?

            • [^] # Re: merci et venv

              Posté par  (site web personnel) . Évalué à 2.

              il dit qu'il n'a plus de genou

            • [^] # Re: merci et venv

              Posté par  . Évalué à 6.

              Il est pourtant clair: Quand on commence à avoir besoin d'un foutoir de conteneurs pour faire coucher un truc codé quick&dirty reposant sur des dépendances tenant de l'alignement des planètes, avec ses semblables… Y'a un moment ou coller les machines les unes a côté des autres, chacune avec son applicatif et son environnement cornecul, n'est peut-être pas moins bête!

              • [^] # Re: merci et venv

                Posté par  (site web personnel) . Évalué à 2.

                Et quand ça tombe en marche, c'est là que tu changes de boite.

              • [^] # Re: merci et venv

                Posté par  . Évalué à 2.

                Ça n'est pas lié à docker. Quand le principe c'est d'utiliser des environnements différents que tu les cloisonne à base de variables d'environnement + liens symboliques, chroot, pyenv, de docker, de machines virtuelles, d'environnement nix,… on est presque dans du détail par rapport au besoin initial.

                https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

          • [^] # Re: merci et venv

            Posté par  . Évalué à 3.

            Un autre xkcd qui m'avait bien fait rigoler.

      • [^] # Re: merci et venv

        Posté par  (site web personnel) . Évalué à 6.

        Mais si vous avez mieux, je suis preneur

        Je ne sais pas si c'est mieux mais perso j'ai beaucoup fait avec Make (python ou pas d'ailleurs). Un petit make env pour l'env, ou un petit make init pour la totale, et c'est parti.

        Adhérer à l'April, ça vous tente ?

        • [^] # Re: merci et venv

          Posté par  (site web personnel) . Évalué à 4.

          make :)

          Que j'adore ! et utilise souvent mais c'est pas franchement un truc de djeune :)

          D'ailleurs le triptyque "Think - edit - make " est toujours vrai même si parfois bon nombre de collègue saute la 1ere partie

      • [^] # Re: merci et venv

        Posté par  . Évalué à 3.

        Je ne sais pas comment tu travail, mais si tu utilise TOUJOURS ton shell peut être que direnv permet d'être plus rigoureux : quand tu va dans ton dossier tu as automatiquement les variables d'environnement qui vont bien ?

        https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

        • [^] # Re: merci et venv

          Posté par  (site web personnel, Mastodon) . Évalué à 4.

          J’utilise le plugin zsh-autoswitch-virtualenv. C’est pour zsh mais ça marche très bien.

          Ça gère les gestionnaires pipenv et poetry (et requirements.txt). Ça marche aussi avec les environnements virtuels créés à la main dans un répertoire .venv du projet.

          Ça ajoute une commande/alias mkvenv qui te crée l’environnement virtuel qui va bien. Ça t’affiche un rappel quand tu vas dans un projet qui n’a pas encore d’environnement virtuel. Et ça active l’environnement dès que tu changes de répertoire (et le désactive quand tu quittes l’arborescence) comme son nom l’indique.

          Sinon le README c’est clairement un truc où j’indique :
          - quelle est la (ou les) version de Python gérée
          - quel gestionnaire de paquet est utilisé (comme ça pas besoin de supposer)
          - quelles commandes sont à faire pour avoir le projet prêt, c’est à dire virtualenv, dépendances installées, initialisation d’une base de données éventuellement, etc.

          Sur quelques projets, j’ai également ajouté un Makefile quand il faut faire un peu plus que deux commandes simples. Mes collègues ne l’utilisent pas, sont trop jeunes pour make :-(

          • [^] # Re: merci et venv

            Posté par  . Évalué à 5.

            Ah pas mal je ne connaissais pas. Pour ce que je fais en python je n'utilise pas d'environnement perso (soit je suis sans dépendance soit j'utilise celles du système).

            Sur quelques projets, j’ai également ajouté un Makefile quand il faut faire un peu plus que deux commandes simples. Mes collègues ne l’utilisent pas, sont trop jeunes pour make :-(

            T'es complètement has been aussi ! Aujourd'hui c'est just qui est à la mode.

            https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

            • [^] # Re: merci et venv

              Posté par  (site web personnel, Mastodon) . Évalué à 3.

              Ah tiens, faut que je regarde c’est rustine. Pourquoi pas au moins jeter un œil si c’est plus simple que make.

              Après, l’avantage des Makefile c’est que t’es à peu près sûr que les linuxiens ont la commande make dispo et fonctionnelle.

              Si faut installer un autre truc pour avoir le truc de départ, tu te retrouves avec un problème de poule et d’œuf. Y’a graddle, pour Java, qui avait essayé de casser cette histoire de poule/œuf avec leur wrapper graddlew mais globalement ça voulait surtout dire que t’embarquais une version figée de graddle dans ton projet. J’en ai vu d’autres utiliser ce système de wrapper, je ne sais plus lesquels.

              Bon pour une rustine c’est plus compliqué tout de même. Faut mettre les version x86_64, armv7, armv8, leur sous-version, risc-V, m1? Bref c’est pas possible pour un petit projet qui veut justement un truc simple sans installer encore autre chose. À moins que ce soit plus facile à installer sur des systèmes comme Windows que Makefile ?

              • [^] # Re: merci et venv

                Posté par  (site web personnel, Mastodon) . Évalué à 3.

                Autre dinosaure ici : je reste à make car présent partout et que la plupart des trucs alternatifs ont la compatibilité avec. Par contre, pour la compatibilité justement (merci pour la découverte) et pour ma tranquillité d’esprit surtout, je fais au plus simple.
                Quand j’ai besoin de trucs plus poussés je regarde cmake. J’ai probablement de la chance de ne pas avoir souvent de besoin un peu avancé, du coup je ne me suis pas trop intéressé aux alternatives qui existent.

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: merci et venv

      Posté par  . Évalué à 8. Dernière modification le 06 novembre 2023 à 20:37.

      J'en parlerai plus en détail dans la deuxième dépêche ☺

      En soi, il n'y a rien de très compliqué avec les environnements virtuels. Leur raison d'être essentielle, c'est de pouvoir utiliser et/ou développer le projet foo et le projet bar avec les dépendances des deux installées, sans qu'elles rentrent en conflit entre elles, ni d'ailleurs en conflit avec des outils écrits en Python de ta distribution Linux.

      Et pour les utiliser, il y a juste quelques commandes à mémoriser :

      # Crée un environnement dans <dossier-environnement>
      python -m venv <dossier-environnement>
      
      # Lance le Python de l'environnement, qui est isolé (il n'a pas
      # accès aux paquets installés système, seulement à la bibliothèque standard)
      <dossier-environnement>/bin/python 
      
      # Installe des paquets dans l'environnement
      <dossier-environnement>/bin/pip install numpy scipy pycowsay
      
      # Lance une commande installée dans l'environnement par pip
      <dossier-environnement>/bin/pycowsay meuh
      
      # "Active" l'environnement en ajoutant son dossier bin/ au début du $PATH
      # du shell.
      source <dossier-environnement>/bin/activate
      
      # Quand l'environnement est activé, on peut travailler plus agréablement :
      
      python # équivalent à <dossier-environnement>/bin/python
      pip # équivalent à <dossier-environnement>/bin/pip
      pycowsay # équivalent à <dossier-environnement>/bin/pycowsay
      
      # Désactive l'environnement
      deactivate
      
      # Supprime l'environnement
      rm -rf <dossier-environnement>

      Là où ça se complique, ce sont les plutôt « bonnes pratiques » avec les environnements, parce qu'elles ne sont pas vraiment standardisées. Il y a beaucoup d'outils qui gèrent des environnements à ta place (pipx, tox, nox, hatch, poetry, pour n'en citer que quelques uns).

      Exemple de confusion : les gens entendent qu'il ne faut pas installer un paquet en dehors d'un environnement virtuel (c'est vrai), ils voient que pycowsay s'installe avec pipx install pycowsay (c'est correct), et ils en déduisent qu'il faut faire ça dans un environnement virtuel (c'est faux, parce que justement, l'intérêt de pipx par rapport à pip, c'est qu'il crée l'environnement tout seul).

      Un autre problème pour les débutants, c'est qu'il faut déjà savoir comment invoquer Python : avec python ou python3 sous Linux (sachant que jusqu'à récemment, python pouvait être Python 2), et avec py sous Windows. Et sous macOS, c'est encore pire vu qu'il y a un Python système, mais aussi pour beaucoup un Python de Homebrew. Même chose avec le source <dossier-environnement>/bin/activate, qui dépend du shell (cette commande marche sous Bash et zsh, pour Powershell ce serait <dossier>\Scripts\Activate.ps1).

      Autre source de confusion : la manière d'installer venv. Sous macOS et Windows, il vient préinstallé, mais certaines distributions Linux ne le mettent pas dans le paquet python pour réduire sa taille. Par exemple, sous Ubuntu, il faut faire sudo apt install python3-venv. Sans compter que certains préfèrent utiliser le module virtualenv au lieu de venv.

      Bref, comme pour beaucoup de choses dans toute cette affaire, il n'y a vraiment rien de compliqué, mais les gens n'y comprennent rien parce que c'est vraiment difficile de donner des instructions qui marchent pour tout le monde sur tous les systèmes et avec tous les outils.

      • [^] # Re: merci et venv

        Posté par  (site web personnel, Mastodon) . Évalué à 5.

        Et sous macOS, c'est encore pire vu qu'il y a un Python système, mais aussi pour beaucoup un Python de Homebrew.

        Euh… Il y a aussi un Python système sous Linux et les gens peuvent se débrouiller pour installer des versions qui ne viennent pas de leur dépôt (et notamment avec Homebrew)
        Sinon, pour les dernières version de MacOS, il n’y a plus de Python et d’autres fournis par Apple

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: merci et venv

          Posté par  . Évalué à 2.

          Euh… Il y a aussi un Python système sous Linux et les gens peuvent se débrouiller pour installer des versions qui ne viennent pas de leur dépôt (et notamment avec Homebrew)

          Oui, bien sûr. Simplement, il me semble qu'il est moins fréquent d'installer des Python qui ne viennent pas de la distribution. Mais il y a de la confusion sous Linux aussi.

          Sinon, pour les dernières version de MacOS, il n’y a plus de Python et d’autres fournis par Apple…

          Je ne suis absolument pas compétent pour macOS, mais de ce que je comprends de l'affaire, le Python qui a été supprimé est un Python 2. Apparemment, il y a encore un Python 3 qui n'est pas préinstallé par défaut mais vient avec les outils en ligne de commande XCode (ensemble qui comprend aussi clang, me semble-t-il). Il y a aussi le Python de Homebrew, le Python de son concurrent MacPorts, et le Python de l'installeur à télécharger sur python.org.

          En tous cas, c'est ce que je comprends d'une recherche et notamment de cet article récent : https://www.jcchouinard.com/install-python-on-macos/ . Mais je me trompe peut-être complètement.

          • [^] # Re: merci et venv

            Posté par  (site web personnel, Mastodon) . Évalué à 4. Dernière modification le 07 novembre 2023 à 02:38.

            Oui et non, ce que je dis par « pas fournis par Apple » c’est que ce n’est « plus préinstallé » (le souci de 2.7 c’est que ce n’est supprimé sur toutes les anciennes versions, mais dans tous les cas Apple ne va plus gérer les mises à jour s’il y en a.)
            Et ça vaut aussi pour Ruby et PHP et certainement PERL : Apple ne fait plus le support, les usagers doivent se débrouiller pour installer d’un canal …qui va assurer aussi les mises à jours. (Release Note de Catalina)

            Scripting language runtimes such as Python, Ruby, and Perl are included in macOS for compatibility with legacy software. Future versions of macOS won’t include scripting language runtimes by default, and might require you to install additional packages. If your software depends on scripting languages, it’s recommended that you bundle the runtime within the app. (49764202)

            Il peut y avoir de la confusion sous Windows aussi. Pour l’instant, je n’ai pas vu deux installations pareilles. Et j’ai rencontré des gens qui installent plusieurs versions et sont incapables de savoir laquelle est en cours d’utilisation et comment sélectionner une de ces nombreuses versions.
            Dans tous les cas, je pense que ces soucis/confusions ne sont pas le fait de Python : les gens doivent faire l’effort de comprendre ce qu’ils ou elles installent.

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: merci et venv

              Posté par  (site web personnel) . Évalué à 2.

              Hem, ça me parait normal de ne plus fournir Python 2.x (2.7 inclus).

              https://www.python.org/doc/sunset-python-2/

              Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

              • [^] # Re: merci et venv

                Posté par  (site web personnel, Mastodon) . Évalué à 3.

                On est bien d’accord sur ce point :) Mon propos ne portait pas sur la version, mais bien sur (à partir de 10.4) : « Future versions of macOS won’t include scripting language runtimes by default, and might require you to install additional packages. » Pour faire un parallèle pour les linuxiens et linuxiennes, ça revient à ne plus avoir du tout Python dans les dépôts de la distribution, pas juste les 2.x ;) Et je pointais le fait pour indiquer qu’il n’y a simplement plus de Python Système…

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

      • [^] # Re: merci et venv

        Posté par  (Mastodon) . Évalué à 8.

        Mon soucis avec venv (que j'utilise bcp, voire systématiquement avec n'importe quel script perso) c'est qu'il n'embarque pas de version de python, tu utilises le python système, avec l'environnement venv.

        Du coup si tu déterres un vieux (et pas si vieux parfois) venv, il ne marche plus parce que ta version de python est trop récente et tu as des incompatibilités : faut mettre les paquets à jour. Et là tu perds l'intérêt du venv.

        En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

        • [^] # Re: merci et venv

          Posté par  . Évalué à 2.

          J'ai observé dans ce dernier cas que souvent des dépôts utilisant venv ont également un environnement virtuel fonctionnel créé avec ce dernier dans le versionnage, c'est un peu un palliatif.
          J'ai hâte du moment où cette partie, la gestion de la version de python, fera partie de l'outil.

          Alcyone

        • [^] # Re: merci et venv

          Posté par  (site web personnel, Mastodon) . Évalué à 4. Dernière modification le 07 novembre 2023 à 11:57.

          C’est la raison principale (choix de la version de Python) pour laquelle j’utilises plutôt virtualenv

          “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: merci et venv

          Posté par  . Évalué à 3.

          Sinon, il y a la possibilité d'en rester (surtout pour ses scripts perso) au python de sa distribution et aux librairies quelle maintient qui s'installent d'un "apt install python-XXX".

          Ma Debian 12 offre quand même 831 paquets à ce rayon.

          Et en prime, même si cela n'évite pas un tri ajouté, les dépendances qui ont justifié un mainteneur ont des chances d'être maintenues dans le temps.

          Plus de venv, ni même de pip… et moins de problèmes à mon sens.

          • [^] # Re: merci et venv

            Posté par  (site web personnel, Mastodon) . Évalué à 5.

            Ça dépend surtout de ce qu’on utilise comme programme (et si on l’on veut de nouvelles fonctionnalités etc.) Si tu veux un bidule qui fait plus-mieux-mieux ou n’est pas empaqueté pour ta distribution, tu te retrouves à devoir tirer les dépendances du bidule ; et les ennuis commencent quand celui-ci tire une dépendance avec une version supérieure (ou l’inverse si tu testes un vieux bidule) à celle du système dont dépendent d’autres du système. (ma phrase est trop longue mais tu vois l’idée.)

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: merci et venv

      Posté par  . Évalué à 3.

      Si c'est pour du dev, poetry est la simplicité même.

      poetry init, poetry add, poetry install et poetry shell, et tu as tout ce qu'il faut, y compris la détection des venvs dans VS Code.

  • # Merci

    Posté par  . Évalué à 5.

    Merci beaucoup, je m’emmêle beaucoup entre pip, venv, (ana)conda (pour ceux avec lequel j'ai un peu lutté).
    Par dépit (et a cause d'un proxy firewall man in the middle) j'ai souvent abandonné (car pas central dans mon besoin).
    Billet un peu "complexe" pour moi, mais très éclaircissant, j'ai hâte de voir la suite (et surtout comment faire cohabiter tout ce b*rd*l :p )

  • # « Pallier à »

    Posté par  . Évalué à 5.

    On m'a signalé qu'il ne faut pas dire « pallier aux limitations » mais bien « pallier les limitations » (et même chose pour « pallier aux lacunes »). Est-ce qu'un modérateur voudrait bien corriger ? Merci !

  • # Catégorie quelques-trucs-en-un et liens avec le packaging système

    Posté par  (site web personnel) . Évalué à 4.

    Tout d'abord un grand merci pour ce chouette article, copieux et bien documenté, et mettant en avant un pan de l'Histoire de notre discipline, ce que j'adore !

    En vue du prochain épisode, je voudrais signaler la catégorie quelques-trucs-en-un avec une production personnelle nommée pip-info (ou pippin :-) ) qui, à ce jour, propose un équivalent tout-en-un des commandes "pip list", "pip list --outdated", "pip show" et "pip-audit". J'ai fait ça à l'origine pour explorer ce que je considérais être des bugs de "pip list --outdated", et puis, comme souvent, je me suis laissé emporter… Dans une version non publiée, j'ai travaillé sur les arborescences de dépendances, amont et aval, des packages Python… avec l'idée d'aller jusqu'aux packages système.

    Je mentionne ce lien avec le packaging système car dans mon système favori, FreeBSD (mais je pense que c'est pareil dans Linux), on encapsule des outils ou packages Python dans des packages systèmes, sans toujours être à jour des dernières versions disponibles. Du coup, quand on a pour politique d'être à la pointe de la modernité, on souffre de l'absence d'interdépendances entre les outils de gestion de packages systèmes et ceux de packages Python… Je gère ça à la main pour le moment, mais je sens qu'un jour je vais écrire quelque chose pour automatiser ce travail.

    Vous êtes peut-être en train de vous dire que c'est un peu extrême de vouloir tout mettre à jour à la fois dans le système et dans Python, mais la réalité c'est que les packages Python systèmes ont parfois pas mal d'écart avec ceux de PyPI (du moins pour les moins courants) et que beaucoup proposent des versions qui ont des problèmes de sécurité connus.

    Pour contrôler cela, j'ai écrit un autre outil, pysec2vuxml, qui m'a permis de montrer que sur près de 4000 packages Python encapsulés dans des packages FreeBSD, environ 1 à 2% avaient des problèmes de sécurité non signalés (NB: c'est la même chose avec les systèmes de packaging de plein d'autres langages…). Cet outil me servait du coup à préparer le signalement de ces problèmes de sécurité au niveau système. Je ne sais pas s'il existe un équivalent de cet outil sur Linux, mais je suis à peu près sûr que le problème y est le même.

    Voilà. J'ai hâte de lire la suite de l'article !

    • [^] # Re: Catégorie quelques-trucs-en-un et liens avec le packaging système

      Posté par  (site web personnel, Mastodon) . Évalué à 4.

      En ce qui concerne les versions en retard dans les paquets de FreeBSD, il ne faut pas hésiter à proposer une montée de version sur le bugzilla : soit le mainteneur ne l’a pas vue, soit il n’a pas le temps, soit il y a un conflit entre différents packages, et ça sera discuté dans le PR.

      • [^] # Re: Catégorie quelques-trucs-en-un et liens avec le packaging système

        Posté par  (site web personnel) . Évalué à 3.

        Bien sûr, et l'outil dont j'ai parlé, pysec2vuxml, génère justement une entrée VuXML pour tous ceux qui ont une vulnérabilité de sécurité non signalée, ainsi qu'un index permettant de contacter l'ensemble des mainteneurs concernés.

        Je mets mainteneur entre guillemets car le terme est souvent inapproprié. Beaucoup de gens (et j'en ai fait partie) créent des ports pour des outils annexes pour pouvoir créer un port pour un de leurs logiciels ou pour un logiciel tiers qui les intéresse, mais ils ne maintiennent plus particulièrement ces ports annexes par la suite. Dans le cas de ports pour des logiciels Python avec des vulnérabilités PYSEC connues, soit il n'y a pas de correctif connu, soit le logiciel source a été abandonné, soit le mainteneur a abandonné l'affaire depuis longtemps !

        • [^] # Re: Catégorie quelques-trucs-en-un et liens avec le packaging système

          Posté par  (site web personnel, Mastodon) . Évalué à 2.

          Ah oui, j’étais passé à côté de pysec2vuxml ! Il faut le faire connaître plus…

          • [^] # Re: Catégorie quelques-trucs-en-un et liens avec le packaging système

            Posté par  (site web personnel) . Évalué à 4.

            Merci Thierry. J'en ai parlé sur la ML FreeBSD security à l'époque, et j'ai travaillé particulièrement avec Philip Paeps de la Security team.

            Bon, ce n'est pas un outil grand public non plus, mais il n'y a pas de raison que je sois le seul à l'utiliser pour le projet. J'ai d'ailleurs sous le coude plein de vulnérabilités non encore signalées, mais j'essaie de ne pas aller plus vite que la capacité de commit de ceux qui traitent les PR.

            2 points à noter :
            - le seul truc manuel est d'écrire le résumé en 1 ligne de la vulnérabilité, mais j'envisageais d'utiliser un "résumeur" IA pour faire un truc complètement automatisé (pas sûr que ça marche bien à moins d'entraîner le modèle à résumer des vulnérabilités)
            - j'ai en cours (je n'ai pas encore écrit le générateur VuXML) une généralisation de pysec2vuxml appelée osv2vuxml qui fait la même chose pour la dizaine de langages qui ont un système de packaging. A l'occasion, il faudra que je le finisse (environ 160 vulnérabilités non répertoriées la dernière fois que je l'ai fait tourner).

            Côté grand public, enfin public intéressé par la sécurité, j'ai aussi écrit un outil appelé vuxml pour interroger la base de données VuXML, en ligne de commande ou via une API Python.

  • # oui c'est la foire.

    Posté par  (site web personnel) . Évalué à 7.

    Le packaging python m'a toujours laissé perplexe, encore plus quand j'ai découvert qu'il y avait aussi conda.
    A chaque fois un gros WTF me remplit les poumons. J'ai à peine commencer à me familiariser avec un outil qu'un autre se pointe. Cette introduction met la lumière sur cette foire.
    Pourquoi conda serait plus adapté pour le packet wheel ? Et pourquoi appeler ça wheel ?
    Que faut il utiliser à la fin ?
    J'espère des réponses dans la suite de cette série d'article.

    • [^] # Re: oui c'est la foire.

      Posté par  (site web personnel) . Évalué à 5.

      Et pourquoi appeler ça wheel ?

      Dans l'espoir de pas la réinventer (la roue) :)

      https://link-society.com - https://kubirds.com

    • [^] # Re: oui c'est la foire.

      Posté par  . Évalué à 6.

      Pourquoi conda serait plus adapté pour le packet wheel ?

      Il y a un malentendu : les wheels sont un format qui n'est pas utilisé par Conda, car Conda a son propre format.

      Conda est plus adapté pour distribuer du code précompilé, et ça, j'en reparlerai dans la troisième dépêche.

      Et pourquoi appeler ça wheel ?

      C'est encore une référence aux Monty Python…

      https://stackoverflow.com/questions/21113163/wheel-is-a-reference-to-the-other-python

      "Wheel" veut dire "roue" mais aussi "meule (de fromage)", et le PyPI est surnommé « cheese shop » d'après le titre d'un sketch des Monty Python, d'où les wheels qu'on récupère au cheese shop.

  • # Simplicité?

    Posté par  . Évalué à -5. Dernière modification le 07 novembre 2023 à 17:29.

    Le langage Python, avec son écrasante popularité (premier au classement TIOBE), est vanté pour sa simplicité.

    Pardon? D'aucuns et pas des manches trouvent le C++ (pour en rester aux langages objet) bien plus simple que Python qui est tout sauf un langage simple. Sauf à confondre simple et lisible (même pour le néophyte s'il est anglophone, mais de là à lui faire prendre le clavier…), à la limite!

    Le C est incomparablement plus simple (niveau grammaire) à apprendre que Python et c'est souvent le cas dans les langages interprétés évolués pour ne pas avoir des performances trop altérées (on complexifie la grammaire pour maximiser ce qui tournera direct dans l'interpréteur/en natif).

    • [^] # Re: Simplicité?

      Posté par  . Évalué à 8.

      Pardon? D'aucuns et pas des manches trouvent le C++ (pour en rester aux langages objet) bien plus simple que Python qui est tout sauf un langage simple. Sauf à confondre simple et lisible (même pour le néophyte s'il est anglophone, mais de là à lui faire prendre le clavier…), à la limite!

      Faut pas exagérer non plus

    • [^] # Re: Simplicité?

      Posté par  (site web personnel) . Évalué à 1.

      Le C/C++ nécessite de maitriser la chaine de compilation ce qui nécessite d'autres compétences.
      Il nécessite aussi une certaine maîtrise du pré-processeur qui a aussi sa syntaxe.
      Et si tu veux faire des
      tu n'as encore rien fait qu'il te faut maitriser deux outils en plus du langage.

      Python est basé sur un interpréteur c'est déjà un plus dans la simplification sur l'utilisation.
      Aussi je vois C/C++ comme des langages de "manipulation" de données en mémoire, à peine structurées (bon plus pour le C++ mais le templating c'est pas une notion si simple à maîtriser).

      Python est bien plus avancé pour la manipulation de données et permet leur introspection sans passer par le debugger.
      Pour arriver son niveau avec le C/C++ il faut ajouter des dépendances sur d'autres bibliothèques, et là aussi le lien est moins évident qu'avec Python.

    • [^] # Re: Simplicité?

      Posté par  (site web personnel) . Évalué à 5.

      Le C et le C++ plus simple que Python ? Je vais rebondir sur le bon troll en ce vendredi.

      Evidemment, il y a plusieurs définitions de simple…

      • Simple pour installer des dépendances: c'est très simple en Python, c'est même le sujet de la dépêche. En C/C++, ce n'est pas simple (sans être particulièrement complexe). Il n'y a pas de convention sur où placer du code externe, la façon de linker une dépendance est très compilateur/platforme dépendante. Et il n'y a pas de dépôt centralisé pour trouver une dépendance. Par exemple, si je veux trouver une lib C qui fait des requêtes http asynchrones, je ne suis pas sûr de savoir où chercher. Et quand je l'aurai trouvé, il me faudra plus qu'une seule ligne de commande pour commencer à l'utiliser.

      • Simple pour faire du code multiplatforme: non, les outils de dev vont changer d'un OS à un autre, alors que Python reste unifié.

      • Simple du genre il y a pas de pièges dans la syntaxe: non, le C/C++ est truffé de possibilités de te tirer une balle dans le pied, que ce soit dans la syntaxe ou dans le runtime. Python en réaction a limité beaucoup de ces chausse-trappes.

      • Simple du genre grammaire simple: pour le C++, je crois pas que quiconque puisse revendiquer que sa syntaxe est simple. Pour le C vs Python, j'aurai tendance à penser que Python reste plus simple à parser. Sachant que pour parser du C, il faut aussi parser un second langage qui est le préprocesseur. Tu as donc deux parseurs fondamentalement à écrire pour parser ce langage. Et en tant qu'humain, tu as deux parseurs à faire tourner dans ton cerveau.

      Honnêtement, je suis assez surpris que tu puisses trouver le C simple à apprendre. J'avoue que quand je dois manipuler des tableaux de pointeurs de fonctions qui retournent des pointeurs, je suis à la ramasse sur comment mettre mes * et je pense pas être le seul. Python a une complexité grandissante au fil des années, mais ça reste à mon sens plus approchable.

      • [^] # Re: Simplicité?

        Posté par  . Évalué à 3.

        "Honnêtement, je suis assez surpris que tu puisses trouver le C simple à apprendre"

        Il n'y a pourtant qu'a mesurer l'épaisseur d'ouvrages traitant du python à un K&R. Et comme avec tout langage capable de tout faire d'un boot loader à l'OS et son applicatif, forcément on est un peu moins à utiliser trop de dépendances évitables qui à mon sens peuvent vite devenir problématiques avec python (entre autres).

        Le C est vraiment simplissime comparé à python niveau syntaxe, ce qui ne veut pas dire que coder un truc (à condition que ce soit possible dans les 2 langages) soit plus rapide/facile en C, surtout si une librairie évite de réinventer la roue. Par contre le lien perdu avec la donnée à traiter peut rendre les choses peu évidentes en python même dans de l'applicatif à mon sens. Puis si l'auteur de la dite librairie abandonne sa maintenance, vogue la (plus souvent les) galère(s) avec un langage qui n'a jamais brillé pour sa compatibilité ascendante (cf passage de python 2 à 3) et ne va donc pas permettre d'éviter des problèmes de moyen terme: On pensait avoir un truc de quelques milliers de lignes python à maintenir reposant sur des librairies maintenues… et on se retrouve à devoir maintenir des dizaines de milliers de lignes de code plus maintenu écrit par d'autres, refaire la partie que l'on utilisait from scratch voir continuer les cochonneries avec un wrapper sur une lib alternative maintenue (pour combien de temps?)…

        • [^] # Re: Simplicité?

          Posté par  . Évalué à 3.

          Le C est vraiment simplissime comparé à python niveau syntaxe,

          Au niveau de la syntaxe c'est faux. Le duff device est un exemple de comment on peut tordre la syntaxe du C, python est plutôt aride et n'a même pas d'opérateur ternaire par exemple. Python ne peux pas écrire d'affectation à la place d'une condition pas exemple. Techniquement le concours d'offusquation est bien moins drôle en python.

          La sémantique de python est plus complexe par contre. Il peu se passer beaucoup de choses pour une ligne de code donnée.

          Par contre le lien perdu avec la donnée à traiter peut rendre les choses peu évidentes en python même dans de l'applicatif à mon sens.

          Tu parle de fuite mémoire ?

          Puis si l'auteur de la dite librairie abandonne sa maintenance,

          Ça existe aussi en C. Par contre en C tu n'est pas outillé pour décrire tes dépendances et donc les faire évoluer. C'est souvent au petit bonheur la chance si l'ABI des dépendances est stable ou non.

          (cf passage de python 2 à 3)

          Reprocher ça a python c'est un peu comme reprocher les nombres à virgule flottantes IEEE 754-1985 de C99. Ça a beaucoup fait parler mais ce n'est un sujet de problème pour personne au quotidien.

          et on se retrouve à devoir maintenir des dizaines de milliers de lignes de code plus maintenu écrit par d'autres, refaire la partie que l'on utilisait from scratch voir continuer les cochonneries avec un wrapper sur une lib alternative maintenue (pour combien de temps?)…

          Tu crois sincèrement que le langage serait aussi populaire si c'était un cas un minimum régulier ?

          https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

          • [^] # Re: Simplicité?

            Posté par  . Évalué à 2. Dernière modification le 24 novembre 2023 à 09:34.

            1) La syntaxe est simple et permet bcp de liberté, car il y a des fois ou cela sert, même si cela peut-être source d'erreurs. Et en python, ne pas avoir d'opérateur ternaire pour un language qui se veut lisible, quand on parle du non sujet des concours de C illisible, c'est ce que j'appelle un sacré manque. Et un manque total de cohérence pour vous.
            On pourrait ajouter les solutions cornecul nécessaires en Python pour pallier à l’absence de variables static, quand on fait du procédural… Pénible. Comme a été pénible de se passer 2 décennies d'un switch/case!

            2) Non. Mais écrire cela situe tout de suite a qui on a affaire.

            3) Oui, mais c'est comparativement rare et les librairies système n'ont aucune chance d'être concernées. Les histoire d'ABI, c'est un simple pb de cohérence du système de build et pas de sources (sauf quand on se lie à des trucs non libres, genre gnu-efi bien obligé de se fader une rupture d'ABI en appelant des services BIOS à coups de wrapper basé sur des listes variables d'arguments, dont tu me diras qu'ils sont aussi source d'erreur car le précompilateur ne peut faire aucune vérification des arguments: OK, mais va dire merci à Intel/Microsoft/AMI/Insyde/Phoenix & co).

            4) Et le print et la division et les changements dans les librairies standards… Tu en devance certains à la relecture ou d'un pylint mais il reste combien de merdes tordues que tu vas te prendre, à l'execution, parfois des semaines après car tu passes pas souvent dans la branche de code concernée (et/ou pas facilement testable). Le problème de python, c'est comme souvent les loupés dans la définition initiale et plus un langage est riche plus on en aura.

            5) Pour faire la boucle avec le sujet de l'article: S'il n'y avait pas ces problème omniprésents côté python, on n'aurait pas besoin de venv & co!

            • [^] # Re: Simplicité?

              Posté par  . Évalué à 1.

              Et en python, ne pas avoir d'opérateur ternaire pour un language qui se veut lisible, quand on parle du non sujet des concours de C illisible, c'est ce que j'appelle un sacré manque. Et un manque total de cohérence pour vous.

              Euh…

              https://docs.python.org/3.12/reference/expressions.html#conditional-expressions ?

            • [^] # Re: Simplicité?

              Posté par  . Évalué à 3.

              La syntaxe est simple et permet bcp de liberté, car il y a des fois ou cela sert, même si cela peut-être source d'erreurs. Et en python, ne pas avoir d'opérateur ternaire pour un language qui se veut lisible, quand on parle du non sujet des concours de C illisible, c'est ce que j'appelle un sacré manque. Et un manque total de cohérence pour vous.

              Tu mélange simplicité et expressivité. Le fait de ne pas avoir implémenté d'opérateur ternaire rend la syntaxe plus simple (un opérateur en moins, l'unique opérateur 3 paramètres, ça fait moins de particularité etc), mais réduit l'expressivité. La limitation de l'expressivité c'est un objectif de python qui ne veut pas que chaque développeurs du langage fasse à sa façon, mais qu'il n'y ai qu'une seule façon de faire.

              On pourrait ajouter les solutions cornecul nécessaires en Python pour pallier à l’absence de variables static, quand on fait du procédural… Pénible. Comme a été pénible de se passer 2 décennies d'un switch/case!

              Je suis parfaitement d'accord que c'était un manque, mais ça contribuait à la simplicité de la syntaxe : au point de la rendre aride selon moi.

              Non. Mais écrire cela situe tout de suite a qui on a affaire.

              Tu viens répondre 13 jours après pour après avoir bien réfléchis te dire que faire des attaques ad hominem c'était une bonne idée ? Tu trouve que c'est normal qu'une discussion au sujet de langages de programmation parte en pugilat ? Faut réduire l'affect python n'est pas une équipe de foot.

              Oui, mais c'est comparativement rare et les librairies système n'ont aucune chance d'être concernées.

              Et ça n'existe pas dans les bibliothèques standards. Entre les bibliothèques "systèmes" qui couvrent un ensemble différent et pas forcément cohérent entre les OS et une bibliothèque standard "pile incluses" qui est disponible partout où tu as accès au langage. C'est une question de choix, perso je trouve que ça se vaut.

              sauf quand on se lie à des trucs non libres

              Le fait de devoir tout reconstruire pour dire qu'on a pas de problème d'ABI est un pi-aller. Sans reconstruire tu peut très bien avoir le problème en utilisant des extensions de ton compilateur qu'il soit libre ou non.

              Et le print et la division et les changements dans les librairies standards…

              C'est les 2 cas les moins parlant. En s'y frottant pour de vrai la gestion des chaînes de caractères est bien plus embêtantes et ne peut pas se gérer automatiquement.

              Le problème de python, c'est comme souvent les loupés dans la définition initiale et plus un langage est riche plus on en aura.

              Et plus en langage est vieux pour il en aura aussi, mais j'ai l'impression que c'est moins le fait d'avoir fait des choix que de vouloir les corriger qui pose problème. Le commité de normalisation du C a tenté de corriger la gestion des nombre à virgule flottante en C99. L’échec me parait bien plus cuisant.

              Pour faire la boucle avec le sujet de l'article: S'il n'y avait pas ces problème omniprésents côté python, on n'aurait pas besoin de venv & co!

              La gestion des dépendances et complexe, mais non tu n'a pas fréquemment des projets qui meurt et leurs utilisateurs qui se retrouvent à supporter des millions de milliards de lignes de code ou tenter des ésotérismes. Bien sûr tu pourra trouver des cas, comme ça arrive dans tous les écosystèmes. Mais pas significativement plus ou moins qu'ailleurs.

              https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

  • # Problème de chronologie

    Posté par  (site web personnel) . Évalué à 1.

    Guido van Rossum a créé le langage Python en 1989.

    C’est en 1998 que le module distutils est né …

    Doit-on en déduire que le développeur de distutils est revenu dans le passé, probablement pour éviter qu'un mauvais développeur ne fasse dérailler le développement de Python avec une version baclée ?

    Plus sérieusement, la page Wikipedia dit que la première version publique de Python date de février 1991, ce que l'on peut constater dans le fichier HISTORY.

    • [^] # Re: Problème de chronologie

      Posté par  (site web personnel) . Évalué à 6.

      Problèmes de lecture ?

      • 1989 → 1998, 9 ans dans le bon sens de l'histoire.
      • Un développement commencé en 1989 pour une première version publique en 1991, ça ne me paraît pas non plus incohérent.

      Wikipedia «In December 1989, Van Rossum had been looking for a "'hobby' programming project that would keep [him] occupied during the week around Christmas" …»

      Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

  • # Enfin c'est clair

    Posté par  (site web personnel) . Évalué à 5.

    Merci. J'ai lu 15 fois les documentations de packaging et les PEP, et ça a toujours été trop technique pour moi. Enfin, j'y comprends quelque chose.

    Lors de ma dernière tentative, j'ai passé trois jours à échouer à utiliser des outils de packaging récent pour terminer avec un setup.py, la solution ultime qui marche.

    Dans les trucs à la con à rajouter, on peut mentionner que l'installation de paquet C/C++ sous linux s'appuie sur l'omniprésence d'un compilateur. Quand tu installes le même outil sous Windows, tu rigoles bien … ou pas en fait. Les outils sont pas super pensés pour gérer ce cas. L'erreur affichée est de plus en plus claire au fil des ans cela dit.

    Autre cas à la con récent, impossible d'installer PIL sous windows avec un "pip install PIL". Alors que le stagiaire arrivait très bien à l'installer le mois dernier. Il m'a fallu du temps pour découvrir que la dernière version n'était publiée que sous forme de paquet source, et donc échouait à la compilation. En demandant une version plus ancienne, j'ai pu obtenir un wheel qui s'installe instantanément.

    Truc à la con agaçant aussi, activer un environnement virtuel (fait avec venv) sous linux se fait avec mon_env/bin/activate et sous windows avec mon_env\script\activate . Il y a sûrement une méga-bonne raison pour passer de bin à script mais c'est relou! Au sein du même outil, pour faire la même chose, c'est deux façon de faire différentes!

    • [^] # Re: Enfin c'est clair

      Posté par  (site web personnel, Mastodon) . Évalué à 3. Dernière modification le 07 novembre 2023 à 19:33.

      Tu as souvent aussi mon_env\bin\Activate.ps1 sous Windows…

      Si tu publies, alors tu fais partie des >900k qui font que setup.py est toujours autant présent :)

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

  • # Merci, j’espère résoudre mon problème !

    Posté par  (site web personnel, Mastodon) . Évalué à 5.

    Merci pour cet état des lieux. Je suis en effet en plein dans un problèmes lié au packaging python.

    Je développe une app python que j’utilise sans aucune installation, juste en lançant le fichier. Je sais des feedbacks utilisateurs que c’est un cas très courant.

    J’ai récemment décidé de séparer ce fichier .py unique en plusieurs parties (4500 lignes de python dans un seul fichier, ça devenait un peu le bazar).

    Or, surprise, il s’avère qu’aucun système de packaging ne permet d’avoir simplement plusieurs fichiers python qui soient exécutables sans installation.

    Je décris le problème ici :

    https://ploum.net/2023-10-01-future-of-offpunk-packaging-hell.html

    Et certains se cassent les dents sérieusement dessus depuis des semaines sur la liste de dev, sans solution. La release de la 2.0 est pour le moment bloquée à cause de ça :-(

    Mes livres CC By-SA : https://ploum.net/livres.html

  • # Lien cassé

    Posté par  (site web personnel) . Évalué à 3.

    Ce lien est désormais cassé : https://docs.python.org/3/distutils/introduction.html

    Celui-là marche : https://docs.python.org/3.10/distutils/introduction.html

    C’est le lien en source de « pour des machines de l’époque comme Solaris et HP-UX ».

    En terme de vieillerie, ça parle aussi de Mandrake Linux:

    Other useful built distribution formats are RPM, implemented by the bdist_rpm command, Solaris pkgtool (bdist_pkgtool), and HP-UX swinstall (bdist_sdux). For example, the following command will create an RPM file called foo-1.0.noarch.rpm:

    python setup.py bdist_rpm
    

    (The bdist_rpm command uses the rpm executable, therefore this has to be run on an RPM-based system such as Red Hat Linux, SuSE Linux, or Mandrake Linux.)

    You can find out what distribution formats are available at any time by running

    python setup.py bdist --help-formats
    

    ce commentaire est sous licence cc by 4 et précédentes

  • # Merci

    Posté par  . Évalué à 2.

    Merci pour cet article bien écrit et super intéressant

  • # Build + distribution SciPy sous Windows

    Posté par  (site web personnel) . Évalué à 4.

    Un lien intéressant qui explique bien les pb de construction de paquets Python pour la distribution multi-plateforme, plus compliqué sous Windows (vu passer sur Hacker News).

    The 'eu' in eucatastrophe – Why SciPy builds for Python 3.12 on Windows are a minor miracle

    Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

  • # Europython 2004

    Posté par  (site web personnel) . Évalué à 1.

    J'avais fait un lightning talk a Europython 2004 sur le problème du pip install qui foire (GCC, etc…), et comment trouver une solution. Dans le fonds de la salle, Guido a répondu qu'il n'y avait pas de problèmes.

    20 ans plus tard, je suis content que Conda existe.

  • # environnement, système et sécurité

    Posté par  . Évalué à 5.

    Pour ma part, j'essaie toujours de coller (et utiliser) au maximum les paquets python de ma distrib (Debian pour ne pas la citer), et de n'installer que le minimum supplémentaire lorsque cela est nécessaire (installation d'un logiciel python avec des dépendances pas toutes présentes dans ma distrib).

    Ma raison, c'est que j'aime bien que apt upgrade fasse l'essentiel du travail de mises à jour de sécurité. Il y a des gens qui surveillent ce qui se passe pour les logiciels de ma distrib, j'aime bien leur faire confiance. Évidemment, avec des logiciels/dépendances externes, c'est plus compliqué, il faut faire plus de veille (et donc ça demande plus de boulot de maintenance/administration).

    J'évite généralement les venv ou virtualenv ou conda ou … : ça installe trop de chose en double (au moins). Évidemment, je sais ce que je fais, et je sais que je peux arriver sur des problèmes difficilement solvables sans ses outils. Mais tant que ce n'est pas le cas, j'évite.

    En pratique, j'essaie de trouver les dépendances nécessaires. J'installe en priorité celles de ma distrib. J'installe les manquantes sur un compte utilisateur (surtout pas dans /usr ou /usr/local) avec (de mémoire) pip install --user --break-system-packages paquet
    Je regarde alors ce qui est installé. Si des sous-dépendances ont été tirées, je les vire (rm .local/lib/python3.11/site-packages/...), j'installe leur version packagée et je recommence avec pip.

    Ça me permet souvent de minimiser les paquets installés avec pip (uniquement ceux non présents dans ma distrib) mais ça veut dire que je n'utilise pas forcément une combinaison de versions très testée par le développeur ou les autres utilisateurs (même si cette combinaison respecte des infos de dépendance).

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.