web-dev-qa-db-fra.com

Qu'est-ce qu'une bonne structure de dossiers pour la distribution multiplateforme d'une application Python?

Désolé pour le mur de texte, mais j'essaie de fournir un bon contexte à ma question. En fait, il y a comme un million de questions ici parce que je suis complètement confus. J'ai récemment appris la programmation Python et créé une application Windows. Maintenant, je veux implémenter cette application et quelques autres idées pour Ubuntu et les publier en tant que GPL-3 open source. Bien que, j'aimerais pour garder le code possible à exécuter sur n'importe quel système (ou au moins à la fois Ubuntu et Windows).

Donc, pour savoir comment fonctionne le packaging Ubuntu, j'ai examiné récemment l'application utilisée dans l'App Developer Showdown. Mais la structure des dossiers et les fichiers qu'elle crée n'ont aucun sens pour moi. J'ai donc lu le buntu Packaging Guide et le Applicaton Review Process avec tous les liens là-bas, ainsi que le Debian Python = Policy . Mais tout ce texte a juste fonctionné pour me rendre plus confus quant à la manière de créer rapidement des fichiers et des dossiers.

Le moyen rapide?

Donc, c'est ce que je comprends rapidement (en supposant que mon nom de projet est proj):

proj/bin = Un seul fichier qui sera copié dans /usr/share/bin/proj.py pour permettre l'exécution de l'application à partir d'un chemin global? Mais ce serait en violation des règles du "Processus d'examen des demandes", n'est-ce pas?
proj/data/* = Fichiers qui devraient se trouver sous/usr/share/proj/*, non? Mais cela serait également contraire aux règles du "Processus d'examen des demandes"?
proj/help/C/* = Une documentation HTML, je pense, qui devrait aller sous/usr/share/doc/proj/et qui fonctionne bien avec "Application Review Process", mais pourquoi le nom du dossier " C "et pas seulement" proj "?
proj/tests/ = Une sorte de fichiers pour un package "test" dans Python. Je suppose que c'est super, j'ai hâte de savoir ce que c'est.
proj/proj/ = Certains fichiers qui semblent simplement se lier à de nouveaux fichiers dans le dossier proj_lib? Semble inutile, et je ne comprends pas pourquoi ceux-ci sont ici du tout.
proj/proj_lib/ = Le code source réel, je suppose?

Puis rapidement crée également proj/apport Et proj/etc/apport* Que je n'ai aucune idée de ce qu'ils font ou pourquoi ils sont ajoutés.

Maintenant, la partie vraiment déroutante est la structure du fichier. Cela ne ressemble à rien de ce que j'ai vu auparavant. Et pour être honnête, cela semble très compliqué de manière inutile. Au-dessous de cette section, je décrirai la façon dont je créerais ma propre structure de fichiers de projet, ce qui pourrait aider à expliquer pourquoi cela est si déroutant pour moi. Mais d'abord, ma compréhension de la voie rapide (notez que ma compréhension peut être erronée à ce stade).

Tout d'abord, le setup.py. Ce fichier contient une fonction appelée update_config () qui charge simplement un autre fichier appelé proj/proj_lib/projconfig.py. Mais ce fichier config.py ne semble pas contenir quoi que ce soit qui serait utile de se séparer du setup.py? En fait, il y a beaucoup de choses que je n'ai jamais vu quelqu'un suggérer de mettre dans un fichier setup.py auparavant. Le fichier setup.py contient également un nom de fichier codé en dur pointant vers l'icône SVG, et sinon, il copie simplement le fichier desktop.in sur lui-même, alors pourquoi ne pas simplement faire les modifications directement dans le fichier desktop.in sans cette fonction dans la configuration .py? Ensuite, il existe une autre fonction pour créer un sous-répertoire proj/data/share/proj et y copier le fichier desktop.in, dont je ne comprends pas le but? Pourquoi avoir une fonction qui fait ça alors que vous pouvez simplement avoir le fichier à l'origine? Puis après tout ce code insensé, quelque chose ressemble à un setup.py normal.

Maintenant, le proj/bin/proj.py, Qui je suppose est censé être utilisé pour démarrer l'application? Cela semble simplement remapper/usr/vers /opt/extras.ubuntu.com/ dans une variable syspath précédemment non déclarée. Donc je suppose que c'est pour s'adapter aux règles du "Processus de révision des applications" pour les applications qui utilisent des noms de dossier standard pour toutes les autres versions de Linux? Très bien, je ne le comprends pas mais je peux vivre avec ça. Après ce remappage des répertoires, ce fichier continue d'appeler proj/proj/ init . Py.

proj/proj/__init__.py Est la façon standard de définir comment démarrer un module, je suppose? Mais au lieu d'avoir du code qui fait quelque chose, ce fichier continue à son tour d'exécuter la classe de fenêtre principale, qui se trouve dans un autre fichier.

proj/proj_lib/ A également un fichier init . Py dont je ne comprends pas le but. Ensuite, il y a un Window.py qui semble contenir la fonctionnalité réelle de l'application, et appelle d'autres fichiers py de fenêtre comme à propos de dialog etc.

La façon dont j'ai fait mon application

Ma structure de dossiers ressemble à ceci:

proj/
proj/ui
proj/imageformats # necessary for imports to work
proj/sqldrivers   # necessary for imports to work

Dans le dossier proj/ J'ai mon setup.py et mon proj.py qui démarre mon application. Dans mon fichier proj.py, j'ai toutes les fonctionnalités de la fenêtre principale, appelant d'autres fenêtres et fonctions avec des importations, et à la fin de ce fichier se trouve le main () fonction qui démarre l'application.

Le dossier proj/ui/ Contient tous mes fichiers .ui créés avec Qt Designer.

Les autres dossiers ne sont là que pour fournir des fichiers qui feront fonctionner l'application lorsqu'elle sera empaquetée avec py2exe pour Windows. Fondamentalement, ce sont les fichiers qui seraient fournis via les dépendances dans Ubuntu.

Notez que cette configuration que j'ai fonctionne très bien pour le développement Windows. J'utilise py2exe pour créer un exécutable qui se retrouve dans un dossier proj/dist/, Et je peux simplement copier les fichiers dans ce dossier et cela fonctionnera sur n'importe quelle machine Windows.

Comment puis-je combiner cela?

J'ai passé quelques jours à essayer de lire la documentation. Il n'y a presque rien que je puisse trouver rapidement, à l'exception du tutoriel de base et des trucs sur les ateliers de démonstration des développeurs d'applications. Je ne trouve rien là-bas qui m'aide à comprendre la structure de dossiers suggérée par rapidement.

D'après ce que j'ai lu, je pourrais utiliser os.environ['HOME'] Pour créer un chemin vers ~/.config/proj.conf sur Ubuntu ou C: /Users/username/.config/proj.conf sur Windows. Jusqu'ici, je peux continuer à croiser du code de plateforme. Mais ensuite, avec la division en/bin et/etc et/opt, je vais commencer à rencontrer des problèmes. Bien sûr, je pourrais en dernier recours garder deux copies du code - une configurée pour Ubuntu et une configurée pour Windows. Mais je souhaiterais quand même une structure de dossiers similaire pour faciliter le transfert des modifications de code.

Il devrait y avoir quelqu'un qui a déjà une bonne solution pour cela. Et peut-être que cette personne pourrait également (en plus de donner un exemple de la façon de le faire multiplateforme) décrire pourquoi il y a une si longue chaîne de fichiers appelant d'autres fichiers appelant d'autres fichiers dans la configuration rapide par défaut? Bien sûr, je suppose maintenant qu'il utilise rapidement une sorte de modèle recommandé pour Ubuntu. Si ce n'est pas le cas, j'aimerais avoir des suggestions sur la structure de dossier recommandée pour distribuer une application via les référentiels Ubuntu?

4
GaRyu

Après beaucoup de recherches sur Google en dehors des pages spécifiques à Ubuntu ou Debian, j'ai trouvé celui-ci qui était en fait plutôt utile. Fondamentalement, la suggestion est de garder quelque chose comme ça:

proj/
proj/bin/proj.py                 # this will just "import proj" and "main()"
proj/proj/__init__.py            # this will just "import window.py" and run that
proj/proj/window.py              # main functionality
proj/proj/submodule/__init__.py  # import in window.py
proj/proj/test/                  # for that test package that quickly also uses
proj/README                      # basic readme file
proj/setup.py                    # standard distutils setup.py

Cela me semble plus sensé que la méthode rapide et plus proche de ma façon originale de le faire. Et il ne devrait pas être impossible d'en faire un paquet Debian qui respecte les directives d'Ubuntu? Je pense donc que je vais simplement effacer les trucs rapidement et le faire. À moins que quelqu'un ait une meilleure suggestion?

Ce qui reste ici est alors "comment puis-je configurer cela pour bien installer sur Ubuntu, ainsi que Windows?", C'est-à-dire dois-je coder setup.py d'une manière spéciale ou faire d'autres considérations dans le code ...

4
GaRyu