web-dev-qa-db-fra.com

Quelle est la bonne façon de travailler avec des modules partagés dans le développement Python?

Je travaille à adopter Python dans le cadre de la suite d'outils de développement de mon équipe. Avec les autres langages/outils que nous utilisons, nous développons de nombreuses fonctions et classes réutilisables qui sont spécifiques au travail que nous faisons. Cela normalise la façon dont nous faisons les choses et économise beaucoup de réinventer les roues.

Je n'arrive pas à trouver d'exemples de la façon dont cela est généralement géré avec Python. En ce moment, j'ai un dossier de développement sur un disque local, avec plusieurs dossiers de projet en dessous, et un dossier "commun" supplémentaire contenant des packages et des modules avec des classes et des fonctions réutilisables. Ces modules "communs" sont importés par des modules dans plusieurs projets.

Development/
    Common/
        Package_a/
        Package_b/
    Project1/
        Package1_1/
        Package1_2/
    Project2/
        Package2_1/
        Package2_2/

En essayant d'apprendre à distribuer une application Python, il semble que l'on suppose que tous les packages référencés sont en dessous du dossier de projet de niveau supérieur, et non collatéraux. La pensée est également venue à Je pense que la bonne approche consiste peut-être à développer des modules communs/framework dans un projet distinct et, une fois testés, à les déployer dans l'environnement de chaque développeur en les installant dans le dossier site-packages. Cependant, cela soulève également des questions concernant la distribution.

Quelqu'un peut-il faire la lumière sur ce point ou me diriger vers une ressource qui traite de cette question?

46
Steve Sawyer

Si vous avez du code commun que vous souhaitez partager entre plusieurs projets, il peut être utile de penser à stocker ce code dans un projet physiquement séparé, qui est ensuite importé en tant que dépendance dans vos autres projets. Ceci est facilement réalisé si vous hébergez votre projet de code commun dans github ou bitbucket, où vous pouvez utiliser pip pour l'installer dans n'importe quel autre projet. Cette approche vous aide non seulement à partager facilement du code commun entre plusieurs projets, mais elle vous aide également à ne pas créer par inadvertance de mauvaises dépendances (c'est-à-dire celles dirigées de votre code commun vers votre code non commun).

Le lien ci-dessous fournit une bonne introduction à l'utilisation de pip et virtualenv pour gérer les dépendances, vaut vraiment la peine d'être lu si vous et votre équipe êtes assez novices pour travailler avec python car il s'agit d'une chaîne d'outils très courante utilisée pour juste ce genre de problème:

http://dabapps.com/blog/introduction-to-pip-and-virtualenv-python/

Et le lien ci-dessous vous montre comment extraire les dépendances de github en utilisant pip:

Comment utiliser Python Logiciel d'installation de Pip, pour extraire des paquets de Github?

12
robjohncox

Le must-read-first sur ce genre de choses est ici:

Quelle est la meilleure structure de projet pour une application Python?

au cas où vous ne l'auriez pas vu (et suivez le lien dans la deuxième réponse).

La clé est que chaque package majeur soit importable comme si "." était le répertoire de niveau supérieur, ce qui signifie qu'il fonctionnera également correctement lorsqu'il est installé dans un site-packages. Cela implique que les principaux packages doivent tous être plats dans le répertoire supérieur, comme dans:

myproject-0.1/
    myproject/
        framework/
    packageA/
        sub_package_in_A/
            module.py
    packageB/
        ...

Ensuite, vous (dans vos autres packages) et vos utilisateurs pouvez importer en tant que:

import myproject
import packageA.sub_package_in_A.module

etc

Ce qui signifie que vous devriez réfléchir sérieusement au commentaire de @ MattAnderson, mais si vous voulez qu'il apparaisse comme un package distribuable séparément, il doit être dans le répertoire supérieur.

Notez que cela ne vous empêche pas (ou vos utilisateurs) de faire un:

import packageA.sub_package_in_A as sub_package_in_A

mais cela vous empêche d'autoriser:

import sub_package_in_A

directement.

10
Ethan Coon

Je pense que c'est la meilleure référence pour créer un package distribuable python:

lien supprimé car il mène à un site piraté.

aussi, ne pensez pas que vous devez tout imbriquer dans un seul répertoire. Vous pouvez faire des choses comme

platform/
    core/
        coremodule
    api/
        apimodule

puis faire des choses comme from platform.core import coremodule, etc.

3
Cameron Sparr

... il semble que l'on suppose que tous les packages référencés se trouvent sous le dossier de projet de niveau supérieur, et non en garantie.

C'est principalement parce que le répertoire de travail actuel est la première entrée dans sys.path par défaut, ce qui rend très pratique l'importation de modules et de packages sous ce répertoire.

Si vous le supprimez, vous ne pouvez même pas importer des éléments du répertoire de travail actuel ...

$ touch foo.py
$ python
>>> import sys
>>> del sys.path[0]
>>> import foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named foo

L'idée m'est également venue à l'esprit que peut-être la bonne approche consiste à développer des modules communs/de structure dans un projet distinct et, une fois testés, à les déployer dans l'environnement de chaque développeur en les installant dans le dossier site-packages.

Ce n'est pas vraiment un enjeu majeur pour le développement. Si vous utilisez le contrôle de version et que tous les développeurs vérifient l'arborescence source dans la même structure, vous pouvez facilement utiliser hacks de chemin relatif pour vous assurer que le code fonctionne correctement sans avoir à jouer avec les variables d'environnement ou liens symboliques.

Cependant, cela soulève également des questions concernant la distribution.

C'est là que les choses peuvent devenir un peu plus compliquées, mais seulement si vous prévoyez de publier des bibliothèques indépendamment des projets qui les utilisent et/ou si plusieurs installateurs de projets partagent les mêmes bibliothèques. Si c'est le cas, jetez un œil à distutils .

Sinon, vous pouvez simplement utiliser les mêmes hacks de chemin d'accès relatifs utilisés dans le développement pour vous assurer que votre projet fonctionne "prêt à l'emploi".

3
Aya