Organisation classique d'un projet python

Le problème exposé dans ce sujet a été résolu.

Bonjour les zesteux,

Je suis débutant en python, mais pas en programmation en général; je viens du Java, du PHP et du C++. Vous m'excuserez si ce que je demande est complètement idiot, mais j'essaie justement de me mettre à python.

Jusqu'à maintenant, je ne suis pas allé au-delà de petits scripts qui font tout au plus quelques centaines de lignes, mais je me rends compte que pour concrétiser une de mes petites idées qui me trottent dans la tête, j'ai intérêt à le faire en python plutôt que Java ou C++ (Java c'est trop lourd pour l'utilisateur lambda, et en C++ je vais me faire ch#"% inutilement pour gérer convenablement du XML, du JSON et du réseau, là où python propose probablement déjà tout ce qu'il faut de manière très simple) Et en plus c'est un bon moyen de monter d'un niveau dans ce langage que je maîtrise pour l'instant que très moyennement.

Comment s'organise-t-on en général dans un projet python ?

Je suis partisan de l'organisation 1 classe = 1 fichier. Problème, en python il semblerait que 1 fichier = 1 module et ce n'est pas ce que je voudrais.

Je n'ai pas envie que le début de tous mes fichiers commencent par 50 lignes de from truc import Truc ou ìmport truc, chose, bidule, machin, blabla, bipbip, ...... interminable......, ou encore devoir systématiquement instancier en version longue monTruc = truc.Truc()`. Ca me paraît étrange que ce soit la norme, et ça me paraît tout aussi idiot qu'il y ait autant de modules que de classes ou autrement dit qu'il n'y ait qu'une classe par module. Je me doute bien qu'on ne met pas non plus la totalité du contenu d'un module dans un seul fichier et qu'on est obligé de faire comme ça, ce n'est pas pratique et pas viable pour un projet qui fera bien plus que quelques centaines de lignes.

Je dois avoir raté un élément évident, mais quoi ? Comment procède-t-on normalement ?

Est-ce qu'il existe une combine pour que quand j'écrive truc = Truc() il charge automatiquement truc.py (un genre d'autoload) ? OU bien qu'il charge d'emblée tous les fichiers .py du répertoire (tant pis pour les performances) ? Ou encore, à défaut d'autre chose, qu'il y ait une fonction require ou include qui ne plante pas lamentablement en cas d'inclusions cycliques ?

Quelle est la bonne manière de faire ? La manière, disons, « standard » ?

Le but final n'est pas de faire une bibliothèque de fonctions, mais bien un programme concret.

Merci pour vos réponses

+1 -0

from math import * (importe toutes les fonctions du module math dans ton module current), mais c'est une pratique déconseillée.

tu peux aussi faire import math as m (ici m est juste un raccourci sur le module math).

tu peux aussi faire from math import sin, cos, tan (pour injecter en une seule ligne)

+1 -0

Je pense que la lecture la plus brute à faire est celle-ci : https://docs.python.org/3/tutorial/modules.html ou trouver les bons tutoriels qui en parlent.

L'important est de comprendre la notion de PYTHONPATH, de l'organisation en modules/packages, de l'importance des __init__.py et du danger des imports circulaires.

Tu peux tout à fait avoir plusieurs classes, fonctions, variables,… dans un même fichier pour ensuite les importer via la syntaxe import module ou from module import objet1, objet2

Importer tout sans vergogne n'est pas conseillé. Il est possible par contre, par exemple avec IPython, d'automatiser l'import d'une extension au lancement de la console : http://ipython.org/ipython-doc/stable/config/intro.html#setting-configurable-options. Ou de regarder du côté de la variable PYTHONSTARTUP.

from math import * (importe toutes les fonctions du module math dans ton module current), mais c'est une pratique déconseillée.

Intéressant, mais ce qu'il me faudrait c'est pas from quelquechose import * mais plutôt un genre de from './*.py' import * si on veut bien. Sinon j'étais déjà au courant pour importer des fonctions ou classes en les renommant.

Regarde comment fonctionne le fichier init.py á la racine de ton package,

Je n'ai aucun fichier puisque je commence un nouveau projet

Tu peux tout à fait avoir plusieurs classes, fonctions, variables,… dans un même fichier pour ensuite les importer via la syntaxe import module ou from module import objet1, objet2

C'est la problématique inverse que je demande: n'avoir qu'une seule classe par fichier, mais que tous les fichiers ne constituent qu'un seul module, idéalement celui par défaut. JE vais aller lire ce que tu me proposes, merci.

+0 -0

C'est la problématique inverse que je demande: n'avoir qu'une seule classe par fichier, mais que tous les fichiers ne constituent qu'un seul module, idéalement celui par défaut. JE vais aller lire ce que tu me proposes, merci.

En Python, un module est un dossier contenant un fichier __init__.py. Par exemple :

1
2
3
4
+ main.py
+ module
    + __init__.py
    + cls.py

Pour faire simple, le fichier __init__.py "importe" automatiquement le fichier class.py (et tous les fichiers Python du dossier en fait), ce qui fait que depuis ton main.py, tu pourras faire :

1
from module.cls import MyClass

Python 3 ne le fait pas automatiquement. Du coup, il faut procéder comme suit, dans le fichier __init__.py.

1
from . import cls

Mais tu peux faire l'import de la classe directement dans le fichier __init__.py :

1
from .cls import MyClass

Et dans main.py :

1
from module import MyClass

Quelques ressources :

+0 -0

Intéressant, mais ce qu'il me faudrait c'est pas from quelquechose import * mais plutôt un genre de from './*.py' import * si on veut bien. Sinon j'étais déjà au courant pour importer des fonctions ou classes en les renommant.

QuentinC

En fait, dans ton cas, tu pourrais très bien avoir à la racine de ton package le module __init__, qui contiendrait tous les imports que tu souhaites. Ainsi, si tu veux facilement donner accès à une classe présente au fin fond du package, il suffirait de l'importer ici.

J'aimerais bien faire en sorte que depuis main.py, je puisse faire ceci :

1
2
3
from monapp import *

machin = Test()

En ayant dans monapp/test.py :

1
2
class Test
. . pass

Note: j'ai ajouté les points pour être sûr que l'indentation ne bug pas; désolé j'ai pas trouvé d'autre moyen, ça foire sinon.

J'ai essayé en mettant ça dans monapp/init.py mais j'ai deux problèmes :

1
2
from . import * # apparament cette instruction ne fait rien...
__all__ = [ 'test' ]

Alors ça marche si dans main.py j'écris machin = test.Test(). Mais vu que je prévois de faire un fichier distinct par classe, chaque instanciation va être inutilement redondante et ça m'embête.

L'autre souci c'est que si j'ajoute un fichier monapp/bidule.py avec une classe Bidule, je suis obligé de mettre à jour init.py. J'aurais voulu que ce soit automatique. Sauf si je fais un machin crado avec quelque chose genre os.walk pour remplir la liste all.

+0 -0

Attention ton fichier doit être monapp/init.pyet non monapp/init.py pour que python le prenne en compte !

C'est bien le cas. Il semblerait qu'il s'agisse d'un bug d'interprétation abusive du markdown. Je croyais que la mise en gras était avec des astérisques et uniquement des astérisques…

Test 1
Test 2
Test 3
Test 4

EDIT: bon, ben c'est bien ça… est-ce que c'est nouveau ? parce qu'il ne semble pas avoir vu cette anomalie en écrivant mon post. Je ne me rappelle pas non plus avoir lu cette variante dans l'aide.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte