Non licet omnibus adire Lexpagum    —  John Duff

Discussions

Python : apprentissage, ide, etc

yaug 1351 Spammeur
Reprise automatique du message précédent.
Comme je commence à multiplier les lignes de codes, je m'approche du coup du besoin de séparer au maximum mon code.

Je me pose des questions sur comment organiser mon modèle de donnée par exemple.
je me suis fait un dossier model avec dedans model.py qui contient mes classes de modèle.
Mais du coup ça commence à devenir bien gros comme fichier et j'aimerais séparer en gardant une partie dans model.py et en créant pour chaque grosse classe un fichier grosseclasse.py, sachant que ces grosses classes utilisent des parties de model.py

par exemple dans model.py j'ai :
import peewee as pw

from config.config import db_config

database_proxy = pw.Proxy()

class MySQLModel(pw.Model):
"""A base model that will use our MySQL database"""
class Meta:
database = database_proxy
Si dans ept.py je déclare :
class EPT(MySQLModel):
uuid = pw.UUIDField(primary_key=True)
created_at = pw.DateTimeField(default=datetime.datetime.now, null=True)
updated_at = pw.DateTimeField(default=datetime.datetime.now, null=True)
share_class_id = pw.ForeignKeyField(ShareClass, null=True)
Ma classe dans le fichier model/ept.py ne connait pas ce qui est dans model/model.py
Du coup... un petit conseil sur comment bien gérer tout ça ?
Guybrush 7842 Bob
Il n'y a pas d'import "automatique" en Python, donc tout ce dont tu as besoin doit être importé. Dans ton "model/ept.py", tu peux ajouter "from model import MySQLModel" (ou "import model" et ensuite "model.MySQLModel").

Vu que tu organises par "répertoires", ça suggère que tu souhaites avoir aussi une hiérarchie dans tes modules. Du coup, je t'invite à créer un fichier "__init__.py" dans le dossier "model". Ce fichier (vide, mais on peut ajouter du code dedans) indique à Python que ton répertoire devient un module, et qu'il est importable (en gros, tout ce qui se trouve dans "__init__.py" deviendra visible si tu fais, depuis le répertoire parent, "from model import *" ou "import model".

Dès l'instant où tu t'organises comme ça, il faut penser à faire tes import "relativement à la racine". C'est à dire que la racine de ton projet sert de "point de départ" pour tes imports : depuis "model/ept.py", tu ne feras plus "from model import MySQLModel" mais "from .model import MySQLModel" (de sorte à explicitement indiquer à Python que tu souhaites partir du module courant (le répertoire "model"), aller dans le module "model" (le fichier model.py) et y récupérer la classe déclarée.

Tout fichier qui sera à la racine pourra accéder au contenu de ces modules via "from model.model import MySQLModel" (le premier "model" est le module/répertoire, le second est le module/fichier). Si depuis un répertoire tu souhaites accéder au contenu d'un autre répertoire, il faudra remonter d'un niveau (from .. import other_module). Mais ça ne marche que si ta racine est elle-même un module (et donc a un fichier vide __init__.py par exemple). C'est similaire à la manière dont on organise un package qui vise à être distribué, mais c'est une bonne habitude d'organiser tes import de cette façon.


Au niveau organisation, si tu as un dossier "model" et plein de "petits fichiers" derrière mais que tu ne souhaites pas avoir à importer chacun de ces fichiers séparémment, tu peux très bien les importer dans le "__init__.py" du répertoire : ils seront alors rendus accessibles dès l'instant où ce module/répertoire est importé. Par ex:

model/A.py contient ClassA
model/B.py contient ClassB
model/C.py contient ClassC

Tu voudrais, depuis la racine (ou un autre module "parallèle") avoir accès à ClassA, ClassB et ClassC:
from model.A import ClassA
from model.B import ClassB
from model.C import ClassC
Mais c'est embêtant. Alors tu fais un __init__.py que tu places dans "model", et dans ce fichier, tu mets:
from .A import ClassA
from .B import ClassB
from .C import ClassC
Ensuite, quand tu souhaites avoir accès à ces 3 trucs là depuis un autre module (parallèle, par exemple), il suffira de faire :
from model import ClassA, ClassB, ClassC


(Au cas où, tu peux jeter un petit coup d'oeil à la deuxième partie de ce document : docs.python-guide.org/wr…)


Ce message a été modifié 1 fois. Dernière modification : 18 septembre 2018 à 09:41 par Guybrush.

yaug 1351 Spammeur
Ok merci pour tous ces retours.

A l'heure actuel j'ai ceci comme arborescence :
main.py
model/model.py
model/ept.py
model/tpt.py
Du coup, cette logique de module s'applique à model ou bien même à ma racine (main.py) ?

Edit : et j'étais justement en train de lire le lien que tu me donnes à la fin :D


Ce message a été modifié 1 fois. Dernière modification : 18 septembre 2018 à 10:01 par yaug.

Guybrush 7842 Bob
Cela s'applique aux "sous-répertoires" de la racine, afin qu'ils soient considérés comme des modules utilisables depuis la racine. Mais si tu as un "sous-répertoire" qui doit accéder à un autre "sous-répertoire", alors il faut aussi un __init__ à la racine.
yaug 1351 Spammeur
Yeap j'ai fini par voir ça.

Du coup, j'essaye de comprendre comment utiliser ma classe Ept.
Pour rappel sa définition dans le fichier model/ept.py:
class Ept(MySqlModel):

Dans mon main, je veux pouvoir utiliser ma classe Ept, sachant que elle même embarque MySqlModel qui est défini dans model/model.py

Tu me suggères de gérer cela comment pour garder ça propre ?

La partie import de python me trouble pour le moment, moi qui vient du monde magique de PHP où quand tu require un fichier, il t'amène tout :D


Ce message a été modifié 1 fois. Dernière modification : 18 septembre 2018 à 11:02 par yaug.

Fabe 561 Geek
yaugLa partie import de python me trouble pour le moment, moi qui vient du monde magique de PHP où quand tu require un fichier, il t'amène tout :D
Mais ce n'est pas magique en PHP non plus. Le seul fichier qu'on veut require, c'est vendor/autoload.php.
Pour le reste, il faut proprement importer ses symboles namespacés, comme partout :-p


Ce message a été modifié 1 fois. Dernière modification : 18 septembre 2018 à 11:17 par Fabe.

yaug 1351 Spammeur
Ouais ouais. Roh..
avant, on faisait un require sur ce que l'on souhaitait.
Désormais avec autoload et les namespace, on require le namespace donné, ce qui n'empèche pas d'avoir un truc plus simple à utiliser je trouve.

Quoi qu'il en soit, à force de relecture des liens filés et de test, j'ai fini par me débrouiller et cela fonctionne désormais, en ayant un truc propre genre ept.Ept pour conserver une clarté de relecture comme conseillé.
Guybrush 7842 Bob
yaugTu me suggères de gérer cela comment pour garder ça propre ?
Tu gardes ta structure actuelle, ça me semble bien :-)
Dans ept.py, tu importes "from .model import MySQLModel", et dans ton fichier "principal" à la racine, tu importes ta classe Ept: "from model.ept import Ept".

Si tu considères que "model.ept" est "trop long" (dans le sens où ça expose une structure interne), alors tu peux le remplacer par "from model import Ept", et dans le "__init__.py" situé dans le répertoire "model", tu ajoutes "from .ept import Ept" (de sorte à ce que __init__ ait connaissance de cette classe, et puisse automatiquement l'exposer quand on importe juste le répertoire).
yaug 1351 Spammeur
J'ai voulu commencer à tester la génération de pdf via le lien que j'avais partagé sur ce topic. La loose. WeasyPrint requiert cairo qui est une abomination à installer sur windows -_-
Je me suis temporairement réorienté sur l'utilisation de xhtml2pdf. Choix par défaut qui fait un peu beaucoup chier.
Fabe 561 Geek
J'ai fait ce type de feature par le passé avec wkhtmltopdf qui donnait un résultat satisfaisant.
Guybrush 7842 Bob
Alors, comment ça avance ton apprentissage du Python ? ;-)

Répondre

Vous devez être inscrit et identifié.