Quelle est la meilleure structure de projet pour une application Python? [fermé]
-
08-07-2019 - |
Question
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 des dossiers du projet?
Les fonctionnalités souhaitables sont la facilité de maintenance, la compatibilité IDE, l’adéquation de la fusion / contrôle du contrôle de source et la génération aisée de packages d’installation.
En particulier:
- Où mettez-vous la source?
- Où mettez-vous les scripts de démarrage d'application?
- Où placez-vous le projet IDE à l'état brut?
- Où placez-vous les tests unitaires / d'acceptation?
- Où mettez-vous des données non Python telles que des fichiers de configuration?
- Où placez-vous les sources non Python telles que C ++ pour les modules d'extension pyd / so binary?
La solution
Peu importe. Tout ce qui vous rend heureux fonctionnera. Il n’ya pas beaucoup de règles stupides car les projets Python 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 les documents d'API générés par Epydoc.
Et le répertoire de niveau supérieur peut contenir des fichiers README, Config et autres.
Le choix difficile consiste à utiliser ou non un arbre /src
. Python ne fait pas la distinction entre /foo
, /bar
et /baz
comme Java ou C.
Etant donné qu'un répertoire quux
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.
-
/quux
-
PYTHONPATH
-
/path/to/quux/foo
Je recommande de placer tout cela sous le " nom-de-mon-produit " annuaire. Donc, si vous écrivez une application nommée QUUX.foo
, le répertoire qui contient tout cela est nommé <=>.
Un autre projet <=> peut alors inclure <=> pour réutiliser le module <=>.
Dans mon cas, puisque j'utilise Komodo Edit, mon fichier IDE est un fichier .KPF unique. En fait, je mets cela dans le répertoire de niveau supérieur <=> et omis de l'ajouter à SVN.
Autres conseils
Selon la structure de système de fichiers d'un Jean-Paul Calderone Projet Python :
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
Ce billet de blog de Jean-Paul Calderone est généralement donné comme réponse dans #python sur Freenode.
Structure de système de fichiers d'un projet Python
Faites:
- 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 une extension.py
, même s’ils sont des 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: puisque sous 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 pouvez vouloir 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 d’utilisateur inclut des utilisateurs Windows, vous voudrez peut-être opter simplement pour le .py extension partout.)- Si votre projet peut être exprimé en tant que fichier source Python unique, placez-le dans le répertoire et nommez-le de la même manière que votre projet. Par exemple,
Twisted/twisted.py
. Si vous avez besoin de plusieurs fichiers source, créez un package à la place (Twisted/twisted/
avec unTwisted/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 l'option de fichier source Python unique ci-dessus était une astuce - vous toujours devez disposer d'au moins un autre fichier pour votre unité. tests). Par exemple,
Twisted/twisted/test/
. Bien sûr, faites-en un paquet avecTwisted/twisted/test/__init__.py
. Placez les tests dans des fichiers tels queTwisted/twisted/test/test_internet.py
.- ajoutez
Twisted/README
etTwisted/setup.py
pour expliquer et installer votre logiciel, si vous vous sentez bien.Ne pas:
- placez votre source dans un répertoire appelé
src
oulib
. Cela rend difficile l'exécution sans installation.- placez vos tests en dehors de votre paquet Python. Cela rend difficile l’exécution des tests sur une version installée.
- créez un package qui uniquement possède un
__init__.py
, puis placez tout votre code dans <=>. Créez simplement un module au lieu d’un package, c’est plus simple.- essayez de créer des hack magiques pour permettre à Python d'importer votre module ou package sans que l'utilisateur ajoute le répertoire qui le contient à son chemin d'importation (via PYTHONPATH ou un autre mécanisme). Ne pas gérez correctement tous les cas et les utilisateurs se fâcheront contre vous lorsque votre logiciel ne fonctionnera pas dans leur environnement.
Découvrez Open Sourcing d'un python Projetez dans le bon sens .
Permettez-moi d'extraire la partie du projet de cet excellent article:
Lors de la configuration d'un projet, la mise en page (ou la structure de répertoires) est importante. 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 avons affaire à 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 à deux endroits
- Sous le répertoire du package 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 aperçu 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 placera la documentation générée), un répertoire sandman et un répertoire de test sous sandman.
L'autorité de conditionnement Python & ";" a un exemple de projet:
https://github.com/pypa/sampleproject
Il s’agit d’un exemple de projet destiné à aider le didacticiel sur l’emballage et la distribution de projets du Guide de l’emballage de Python.
Essayez de démarrer le projet en utilisant le modèle python_boilerplate . Il suit en grande partie les meilleures pratiques (par exemple, ces ici ), mais convient mieux au cas où vous seriez prêt à scinder votre projet en plusieurs œufs à un moment donné (et croyez-moi, avec tout, sauf les projets les plus simples, vous le ferez. Une des situations courantes utiliser une version modifiée localement de la bibliothèque de quelqu'un d'autre).
-
Où placez-vous la source?
- Pour les projets de taille décente, il est judicieux de scinder la source en plusieurs oeufs. Chaque oeuf irait comme un setuptools-layout séparé sous
PROJECT_ROOT/src/<egg_name>
.
- Pour les projets de taille décente, il est judicieux de scinder la source en plusieurs oeufs. Chaque oeuf irait comme un setuptools-layout séparé sous
-
Où placez-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.
- L'option idéale consiste à enregistrer le script de démarrage de l'application en tant que
-
Où placez-vous le projet IDE?
- Dépend de l'IDE. Beaucoup d’entre eux conservent leurs données
PROJECT_ROOT/.<something>
à la racine du projet, ce qui est bien.
- Dépend de l'IDE. Beaucoup d’entre eux conservent leurs données
-
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 utiliserpy.test
pour les exécuter.
- Chaque oeuf a un ensemble de tests séparé, conservé dans son répertoire
-
Où mettez-vous des données non Python telles que des fichiers de configuration?
- Cela dépend. Il peut exister différents types de données non Python.
- & "Ressources &"; , c’est-à-dire les données qui doivent être conditionné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
pkg_resources
le package. - " 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 quand l'application commence à courir. 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, on peut 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
lors du déploiement de Linux.
- & "Ressources &"; , c’est-à-dire les données qui doivent être conditionné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
- Cela dépend. Il peut exister différents types de données non Python.
- Où placez-vous les sources non Python telles que C ++ pour les modules d'extension pyd / so binary?
- dans
PROJECT_ROOT/src/<egg_name>/native
- dans
La documentation est généralement classée dans PROJECT_ROOT/doc
ou PROJECT_ROOT/src/<egg_name>/doc
(cela dépend si vous considérez certains des œufs comme des projets volumineux distincts). Certaines configurations supplémentaires seront dans des fichiers tels que PROJECT_ROOT/buildout.cfg
et PROJECT_ROOT/setup.cfg
.
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 trunk 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é.
Il est préférable de regrouper vos données Python dans vos modules Python en utilisant le package_data
support de setuptools Une chose que je recommande fortement consiste à 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 qui consiste à placer les packages dans com.yourcompany.yourproject
(et pouvant disposer d'un com.yourcompany.utils
espace de noms partagé).
En ce qui concerne 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 avoir renommés; Le Bazaar est particulièrement efficace à cet égard.
Contrairement à d'autres réponses ici, je suis +1 sur le fait d'avoir un répertoire de niveau supérieur 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 prise en main 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 des codes, si vous utilisez <=>).