web-dev-qa-db-fra.com

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

Imaginez que vous souhaitiez développer une application de bureau (non Web) non-triviale pour l'utilisateur final en Python. Quel est le meilleur moyen de structurer la hiérarchie de dossiers du projet?

Les fonctionnalités souhaitables sont la facilité de maintenance, la convivialité IDE, l’adéquation de la fusion/contrôle de contrôle de source et la génération facile de packages d’installation.

En particulier:

  1. Où mettez-vous la source?
  2. Où mettez-vous les scripts de démarrage d'application?
  3. Où mettez-vous le IDE projet cruft?
  4. Où placez-vous les tests unitaires/d'acceptation?
  5. Où mettez-vous des données non Python telles que des fichiers de configuration?
  6. Où placez-vous des sources non Python telles que C++ pour les modules d'extension pyd/so binary?
674
kbluck

Peu importe trop. Tout ce qui vous rend heureux fonctionnera. Il n'y a pas beaucoup de règles stupides parce que Python projets peuvent être simples.

  • /scripts ou /bin pour ce type d'interface de ligne de commande
  • /tests pour vos tests
  • /lib pour vos bibliothèques en langage C
  • /doc pour la plupart de la documentation
  • /apidoc pour la documentation de l'API générée par Epydoc.

Et le répertoire de niveau supérieur peut contenir les fichiers README, Config et autres.

Le choix difficile consiste à utiliser ou non un arbre /src. Python n'a pas de distinction entre /src, /lib et /bin comme Java ou C.

Etant donné qu'un répertoire /src de niveau supérieur est considéré comme dépourvu de sens, votre répertoire de niveau supérieur peut être l'architecture de niveau supérieur de votre application.

  • /foo
  • /bar
  • /baz

Je recommande de mettre tout cela dans le répertoire "nom-de-mon-produit". Donc, si vous écrivez une application nommée quux, le répertoire qui contient tout ce contenu est nommé /quux.

Un autre projet PYTHONPATH peut alors inclure /path/to/quux/foo pour réutiliser le module QUUX.foo.

Dans mon cas, depuis que j'utilise Komodo Edit, mon IDE cuft est un fichier .KPF unique. En fait, je mets cela dans le répertoire /quux de niveau supérieur et omet de l'ajouter à SVN.

347
S.Lott

Selon Jean-Paul Calderone Structure de système de fichiers d'un projet Python :

Project/
|-- bin/
|   |-- project
|
|-- project/
|   |-- test/
|   |   |-- __init__.py
|   |   |-- test_main.py
|   |   
|   |-- __init__.py
|   |-- main.py
|
|-- setup.py
|-- README
226
cmcginty

This article de blog de Jean-Paul Calderone est généralement donné comme réponse en #python sur Freenode.

Structure de système de fichiers d'un projet Python

Faire:

  • nommez le répertoire quelque chose en rapport avec votre projet. Par exemple, si votre projet s'appelle "Twisted", nommez le répertoire de niveau supérieur pour ses fichiers source Twisted. Lorsque vous publiez des versions, vous devez inclure un suffixe de numéro de version: Twisted-2.5.
  • créez un répertoire Twisted/bin et placez-y vos fichiers exécutables, le cas échéant. Ne leur donnez pas l'extension .py, même s'il s'agit de fichiers source Python. Ne mettez aucun code dedans sauf une importation et un appel à une fonction principale définie quelque part ailleurs dans vos projets. (Légère erreur: étant donné que, dans Windows, l'interpréteur est sélectionné par l'extension de fichier, vos utilisateurs Windows veulent en fait l'extension .py. Ainsi, lorsque vous compilez pour Windows, vous souhaiterez peut-être l'ajouter. Malheureusement, il n'y a pas de solution facile pour distutils qui Je sais que pour automatiser ce processus. Considérant que sur POSIX, l’extension .py n’est qu’une verrue, alors que sous Windows le manque est un bogue réel, si votre base utilisateur inclut des utilisateurs Windows, vous voudrez peut-être opter pour le .py extension partout.)
  • Si votre projet peut être exprimé en tant que fichier source unique Python, placez-le dans le répertoire et nommez-le en relation avec votre projet. Par exemple, Twisted/twisted.py. Si vous avez besoin de plusieurs fichiers source, créez un package à la place (Twisted/twisted/, avec un Twisted/twisted/__init__.py vide) et placez-y vos fichiers source. Par exemple, Twisted/twisted/internet.py.
  • placez vos tests unitaires dans un sous-package de votre package (remarque - cela signifie que la seule option de fichier source Python ci-dessus était une astuce - vous toujours nécessite au moins un autre fichier pour vos tests unitaires). Par exemple, Twisted/twisted/test/. Bien sûr, faites-en un paquet avec Twisted/twisted/test/__init__.py. Placez les tests dans des fichiers tels que Twisted/twisted/test/test_internet.py.
  • ajoutez Twisted/README et Twisted/setup.py pour expliquer et installer votre logiciel, respectivement, si vous vous sentez bien.

Ne pas:

  • placez votre source dans un répertoire appelé src ou lib. Cela rend difficile l'exécution sans installation.
  • placez vos tests en dehors de votre package Python. Cela rend difficile l'exécution des tests sur une version installée.
  • créez un package qui uniquement a un __init__.py, puis placez tout votre code dans __init__.py. Créez simplement un module au lieu d’un package, c’est plus simple.
  • essayez de créer des hacks magiques pour permettre à Python d'importer votre module ou package sans que l'utilisateur ajoute le répertoire le contenant à son chemin d'importation (via PYTHONPATH ou un autre mécanisme). vous ne gérerez pas correctement tous les cas et les utilisateurs se mettront en colère contre vous lorsque votre logiciel ne fonctionnera pas dans leur environnement.
214
Adrian

Départ Ouvrir la recherche d'un Python Project the Right Way .

Permettez-moi d'extraire la partie de la mise en page du projet de cet excellent article:

Lors de la configuration d'un projet, il est important que la disposition (ou la structure de répertoires) soit correcte. Une disposition judicieuse signifie que les contributeurs potentiels n'ont pas à dépenser pour toujours pour un morceau de code; les emplacements de fichiers sont intuitifs. Comme nous traitons d'un projet existant, cela signifie que vous devrez probablement déplacer certaines choses.

Commençons par le haut. La plupart des projets contiennent un certain nombre de fichiers de niveau supérieur (tels que setup.py, README.md, Requirements.txt, etc.). Il y a ensuite trois répertoires que chaque projet devrait avoir:

  • Un répertoire de documentation contenant la documentation du projet
  • Un répertoire nommé avec le nom du projet qui stocke le package Python actuel
  • Un répertoire de test à l’un des deux endroits
    • Sous le répertoire du paquet contenant le code de test et les ressources
    • En tant que répertoire de niveau supérieur autonome Pour avoir une meilleure idée de la manière dont vos fichiers doivent être organisés, voici un instantané simplifié de la mise en page de l'un de mes projets, sandman:
$ pwd
~/code/sandman
$ tree
.
|- LICENSE
|- README.md
|- TODO.md
|- docs
|   |-- conf.py
|   |-- generated
|   |-- index.rst
|   |-- installation.rst
|   |-- modules.rst
|   |-- quickstart.rst
|   |-- sandman.rst
|- requirements.txt
|- sandman
|   |-- __init__.py
|   |-- exception.py
|   |-- model.py
|   |-- sandman.py
|   |-- test
|       |-- models.py
|       |-- test_sandman.py
|- setup.py

Comme vous pouvez le constater, il existe des fichiers de niveau supérieur, un répertoire docs (généré est un répertoire vide dans lequel sphinx mettra la documentation générée), un répertoire sandman et un répertoire de test sous sandman.

107
David C. Bishop

"Python Packaging Authority" a un exemple de projet:

https://github.com/pypa/sampleproject

Il s'agit d'un exemple de projet destiné à faciliter le didacticiel sur le packaging et la distribution de projets du Python Packaging Guide de l'utilisateur.

25
guettli

Essayez de démarrer le projet en utilisant le modèle python_boilerplate . Il suit en grande partie les meilleures pratiques (par exemple celles-ci ), mais convient mieux si vous êtes prêt à scinder votre projet en plusieurs œufs à un moment donné (et croyez-moi, avec autre chose que la Les projets les plus simples, vous le ferez. Une situation courante est celle où vous devez utiliser une version modifiée localement de la bibliothèque de quelqu'un d'autre).

  • Où mettez-vous la source?

    • Pour les projets de taille décente, il est judicieux de scinder la source en plusieurs œufs. Chaque oeuf irait comme un setuptools-layout séparé sous PROJECT_ROOT/src/<Egg_name>.
  • Où mettez-vous les scripts de démarrage d'application?

    • L'option idéale consiste à enregistrer le script de démarrage de l'application en tant que entry_point dans l'un des oeufs.
  • Où placez-vous le IDE projet cruft?

    • Dépend de l'IDE. Beaucoup d’entre eux gardent leur matériel dans PROJECT_ROOT/.<something> à la racine du projet, et c’est très bien.
  • Où placez-vous les tests unitaires/d'acceptation?

    • Chaque oeuf a un ensemble de tests séparé, conservé dans son répertoire PROJECT_ROOT/src/<Egg_name>/tests. Personnellement, je préfère utiliser py.test pour les exécuter.
  • Où mettez-vous des données non Python telles que des fichiers de configuration?

    • Ça dépend. Il peut exister différents types de données non Python.
      • "Ressources" , c’est-à-dire les données qui doivent être emballées dans un oeuf. Ces données sont placées dans le répertoire Egg correspondant, quelque part dans l'espace de noms du paquet. Il peut être utilisé via le package pkg_resources.
      • "Fichiers de configuration" , c'est-à-dire des fichiers non Python qui doivent être considérés comme externes aux fichiers source du projet, mais doivent être initialisés avec certaines valeurs lorsque l'application démarre. Pendant le développement, je préfère conserver ces fichiers dans PROJECT_ROOT/config. Pour le déploiement, il peut y avoir différentes options. Sous Windows, vous pouvez utiliser %APP_DATA%/<app-name>/config, sous Linux, /etc/<app-name> ou /opt/<app-name>/config.
      • Fichiers générés , c’est-à-dire des fichiers pouvant être créés ou modifiés par l’application lors de son exécution. Je préférerais les conserver dans PROJECT_ROOT/var pendant le développement et sous /var pendant le déploiement de Linux.
  • Où placez-vous des sources non Python telles que C++ pour les modules d'extension pyd/so binary?
    • Dans PROJECT_ROOT/src/<Egg_name>/native

La documentation doit généralement aller dans PROJECT_ROOT/doc ou PROJECT_ROOT/src/<Egg_name>/doc (cela dépend si vous considérez certains des œufs comme un grand projet séparé). Certaines configurations supplémentaires seront dans des fichiers tels que PROJECT_ROOT/buildout.cfg et PROJECT_ROOT/setup.cfg.

16
KT.

D'après mon expérience, ce n'est qu'une question d'itération. Mettez vos données et votre code où que vous pensiez. Les chances sont, vous aurez tort quand même. Mais une fois que vous avez une meilleure idée de la façon dont les choses vont évoluer, vous êtes beaucoup mieux placé pour faire ce type de conjectures.

En ce qui concerne les sources d'extension, nous avons un répertoire Code sous le tronc qui contient un répertoire pour python et un répertoire pour diverses autres langues. Personnellement, je suis plus enclin à essayer de placer n'importe quel code d'extension dans son propre référentiel la prochaine fois.

Cela dit, je reviens à mon point de départ: ne faites pas une grosse affaire. Placez-le quelque part qui semble fonctionner pour vous. Si vous trouvez quelque chose qui ne fonctionne pas, il peut (et devrait) être changé.

14
Jason Baker

Les données non-Python sont mieux intégrées dans vos modules Python à l'aide du support package_data de setuptools . Une chose que je recommande fortement est d’utiliser des packages d’espaces de noms pour créer des espaces de noms partagés pouvant être utilisés par plusieurs projets - un peu comme la convention Java consistant à placer des packages dans com.yourcompany.yourproject (et de pouvoir disposer d’un partage com.yourcompany.utils espace de noms).

Pour ce qui est de la création de branches et de fusions, si vous utilisez un système de contrôle de code source assez bon, il gérera les fusions même après les renommer; Bazar est particulièrement doué pour ça.

Contrairement à d'autres réponses ici, je suis sur +1 d'avoir un répertoire de niveau src (avec les répertoires doc et test à côté). Les conventions spécifiques pour les arborescences de répertoires de documentation varient en fonction de ce que vous utilisez. Sphinx , par exemple, a ses propres conventions prises en charge par son outil de démarrage rapide.

S'il vous plaît, veuillez utiliser setuptools et pkg_resources; cela facilite beaucoup la tâche à d'autres projets de s'appuyer sur des versions spécifiques de votre code (et l'installation simultanée de plusieurs versions avec différents fichiers autres que du code, si vous utilisez package_data).

7
Charles Duffy