Condition sur les imports / python

Résolu

Bonjour,

Je viens vers vous car j'ai du mal pour trouver la meilleure optimisation de mes algorithmes.

Je m'explique : j'ai un fichier nommé

gen.py

qui s'exécute en important des paramètres, des informations supplémentaires, comme par exemple des URL, des clés d'API, etc. Ces paramètres, sont situés dans un fichier appelé :

param.py

Cependant, j'ai plusieurs fichiers de paramètres, param_1.py, param_2.py, param_3.py, etc.

Donc, l'idée que j'ai eu est de passer en argument à gen.py des numéros tels que 1,2,3 etc. en fonction du fichier de paramètre que je veux prendre en compte. Ainsi, à l'intérieur du script gen.py, j'écris une condition sur cet argument, pour importer le bon fichier de paramètre.

Seulement, voici le début de mon script :

from param import url, key, ssl, outputdir, fls, vadl
try:
    from param import wdt
except ImportError:
    wdt = False

try:
    from param import lctgs
except ImportError:
    lctgs = True

try:
    from param import idl
except ImportError:
    idl = False

try:
    from param import eat
except ImportError:
    eat = []

J'ai plusieurs fois l'import de param, donc il faudrait que chaque if englobe tout ce code, par exemple mon if serait du type :

if (sys.argv ==1):
   from param_1 import ...

Cela ne me semble pas très optimisé, je voulais donc savoir s'il y avait une meilleure solution ?

Je ne l'ai pas précisé, mais ensuite il y aura Crontab qui lancera un script (script.sh) qui lui lancera les commandes :

python3 gen.py 1
python3 gen.py 2 
...

Avec vérification des erreurs.

J'ai donc aussi penser à faire sur ce script (script.sh) une modification de noms des fichiers param, par exemple exécuter un par un le cas 1,2,3 etc. et à chaque fois faire :

mv param_1.py param.py
python3 gen.py

...

Mais bon, ça ne me semble pas terrible

2 réponses

  1. Bonjour 

    merci de forcer le langage python quand tu postes un code


    1. Modérateur

      Bonjour,

      Il me paraît plus naturel d'avoir un seul fichier param.py qui expose une fonction load_params(i) et qui en fonction de i retourne le jeu de paramètres adéquat. Rien ne t'empêche ensuite de faire en sorte que load_param charge des informations depuis différents modules python en fonction de la valeur de i.

      Ensuite, des paramètres sont comme leur nom l'indique... des paramètres. Donc quelque chose que l'utilisateur peut régler. Généralement, un utilisateur fournit les paramètres :

      • de manière interactive :
        • au travers d'une interface utilisateur (graphique ou texte), mettant en jeu éventuellement des fichiers tiers
      • au lancement du programme :
        • au travers d'un fichier de configuration (par exemple un fichier .ini ou .json)
        • au travers des paramètres passés au programme en ligne de commande, mettant en jeu éventuellement des fichiers tiers

      Dans ton cas, j'ai l'impression que ton programme doit simplement prendre en paramètre un fichier de configuration dans lequel sont définis les paramètres (URL, clés d'API, etc). Tu peux par exemple t'inspirer de cet exemple.

      Bonne chance

      1. Bonjour et merci pour ta réponse.

        De ce que j'ai compris, j'aurais donc un seul fichier param.py avec à l'intérieur une fonction load_param(i) qui serait appelée dans un for (par exemple) qui traitera toutes les valeurs de i possibles.

        Donc ensuite, gen.py importe ce module param.py, qui renvoie les différentes en fonction de i c'est cela ?

        Pour mieux comprendre, le fichier param.py contient :

        url = 'https://IP/'
        
        key = 'xxxx'
        
        outputdir = 'output'
        
        fs = {'pubd':'true'}
        
        id = False
        
        vadl = ['0', '1', '2', '3', '4', '5']
        
        eat = []
        
        wdt = False
        
        wlt = True

        Et à savoir que chaque valeur peut changer en fonction des "i".

        En fait, il vaut mieux que je modifie mon script gen.py, que je lui fasse prendre les 9 paramètres en arguments et que ces paramètres soient donnés par le script param.py qui traite tous les cas possibles, non ? Est-ce optimisé ?

        Ok donc j'ai lu la deuxième partie de ton message, cela revient à ce que j'ai dit juste avant, sauf que tu dis que je peux directement donner le fichier contenant les paramètres en argument c'est cela ?

      2. Modérateur
        @Telnaz

        Oui c'est ça.

        params.py

        def load_params(i):
            if i == 0:
                return {
                   "key" : "xxx",
                   "output_dir" : "output",
                   # ...
                }
            elif i == 1:
                return {
                   "key" : "yyy",
                   "output_dir" : "output2",
                   # ...
                }
            #...
            else:
                raise RuntimeError(f"load_params: Invalid i parameter: {i}")

        main.py

        import sys
        from optparse import OptionParser
            
        def main():
            parser = OptionParser()
            parser.add_option(
                "-i", "--config-index",
                metavar = "INT",
                type    = "int",
                dest    = "config_index",
                help    = "Index of the configuration. 0 = ... ; 1 = ...",
                default = 0
            )
            (options, args) = parser.parse_args()
            print(f"options.config_index = {options.config_index}")
            params = load_params(options.config_index)
            print(params)
            # ...
            return 0
                
        if __name__ == "__main__":
            sys.exit(main())

        Exécution

        (mando@silk) (~) $ python3 toto.py -i 1
        options.config_index = 1
        {'key': 'yyy', 'output_dir': 'output2'}
        
        (mando@silk) (~) $ python3 toto.py --config-index 1
        options.config_index = 1
        {'key': 'yyy', 'output_dir': 'output2'}
        
        (mando@silk) (~) $ python3 toto.py -i 0
        options.config_index = 0
        {'key': 'xxx', 'output_dir': 'output'}
        
        (mando@silk) (~) $ python3 toto.py
        options.config_index = 0
        {'key': 'xxx', 'output_dir': 'output'}
        

        Ici j'ai pris un entier mais tu peux imaginer travailler avec une chaîne, un booléan, bref ce qui est adapté à tes besoins (voir un tutoriel sur optparse). Ton programme peut bien évidemment avoir plusieurs options. On pourrait d'ailleur imaginer que tu aies un paramètre en ligne de commande pour chacun de tes paramètres (url de l'api, output_dir, etc...) + un paramètre qui les initialise toute en chargeant un fichier de configuration (ini ou json). On évite toutefois de mettre les clés en paramètres car sinon elles apparaissent en clair dans la table des processus.

        Bonne chance

      3. @mamiemando

        Ok, merci beaucoup.

        J'ai donc adapté le script gen.py (ou main.py), pour récupérer les différents paramètres et les mettre dans des variables globales, comme ceci :

        url = ""
        key = ""
        output_dir = ""
        
        # [...]
        
        def main():
        
           # [...]
        
            global url
            url = params["url"]
            global key
            key = params["key"]
            global output_dir
            output_dir = params["output_dir"]
        
            return 0
        
        # We launch the search for parameters
        main()
        
        
        # [...]

        J'ai juste une petite question, la ligne

        if __name__ == '__main__': 
              sys.exit(main())

        signifie que la fonction main est exécuté seulement si le script exécuté en ligne de commande, et non importé c'est cela ?

      4. Modérateur
        @Telnaz

        • Concernant ton script, je te déconseille l'utilisation de variables globales. C'est généralement une mauvaise habitude car ça nuit à la lisibilité (on ne voit pas l'ensemble des paramètres d'une fonction) et ça peut avoir des effets de bords gênant (programmation parallèle). Mieux vaut les passer explicitement en paramètres.

        • Concernant les deux lignes en fin de fichier, oui cela sert quand on exécute le script python en ligne de commande.

        • Est-ce que ton problème est résolu ou as-tu d'autres questions ?

      5. @mamiemando

        • Pour les variables globales, j'ai fait ceci car je souhaite avoir y accès, après modification de celles-ci dans la fonction, dans le reste du code. Tous les paramètres "url", "key", sont repris par la suite, j'ai donc besoin des valeurs.

        • Ok merci.

        • Je passe le problème en résolu !