115 votes

En Python, puis-je appeler le main() d'un module importé ?

En Python, j'ai un module myModule.py où je définis quelques fonctions et un fichier main() qui prend quelques arguments en ligne de commande.

J'appelle généralement ce main() depuis un script bash. Maintenant, je voudrais tout mettre dans un petit fichier paquet J'ai donc pensé que je pourrais peut-être transformer mon simple script en un script Python et le mettre dans le paquet.

Alors, comment je fais pour appeler le main() fonction de monModule.py à partir de la fonction main() de MyFormerBashScript.py ? Est-ce que je peux le faire ? Comment puis-je passer n'importe quel arguments à ce sujet ?

140voto

Martijn Pieters Points 271458

C'est juste une fonction. Importez-la et appelez-la :

import myModule

myModule.main()

Si vous devez analyser les arguments, vous avez deux possibilités :

  • Analysez-les dans main() mais passe en sys.argv comme paramètre (tout le code ci-dessous dans le même module myModule ) :

    def main(args):
        # parse arguments using optparse or argparse or what have you
    
    if __name__ == '__main__':
        import sys
        main(sys.argv[1:])

    Maintenant vous pouvez importer et appeler myModule.main(['arg1', 'arg2', 'arg3']) d'un autre module.

  • Avoir main() acceptent les paramètres qui sont déjà analysés (encore une fois, tout le code dans le fichier myModule ) :

    def main(foo, bar, baz='spam'):
        # run with already parsed arguments
    
    if __name__ == '__main__':
        import sys
        # parse sys.argv[1:] using optparse or argparse or what have you
        main(foovalue, barvalue, **dictofoptions)

    et d'importer et d'appeler myModule.main(foovalue, barvalue, baz='ham') ailleurs et en passant des arguments python si nécessaire.

L'astuce ici est de détecter quand votre module est utilisé comme un script ; lorsque vous exécutez un fichier python comme le script principal ( python filename.py ) non import est utilisée, alors python appelle ce module "__main__" . Mais si ce même filename.py est traité comme un module ( import filename ), alors python l'utilise comme nom de module à la place. Dans les deux cas, la variable __name__ est définie, et le test par rapport à cela vous indique comment votre code a été exécuté.

51voto

barry solomon Points 641

La réponse de Martijen est logique, mais il lui manquait un élément crucial qui peut sembler évident pour d'autres mais que j'ai eu du mal à comprendre.

Dans la version où vous utilisez argparse, vous devez avoir cette ligne dans le corps principal.

args = parser.parse_args(args)

Normalement, lorsque vous utilisez argparse juste dans un script, vous écrivez simplement

args = parser.parse_args()

et parse_args trouvent les arguments de la ligne de commande. Mais dans ce cas, la fonction principale n'a pas accès aux arguments de la ligne de commande, donc vous devez dire à argparse quels sont les arguments.

Voici un exemple

import argparse
import sys

def x(x_center, y_center):
    print "X center:", x_center
    print "Y center:", y_center

def main(args):
    parser = argparse.ArgumentParser(description="Do something.")
    parser.add_argument("-x", "--xcenter", type=float, default= 2, required=False)
    parser.add_argument("-y", "--ycenter", type=float, default= 4, required=False)
    args = parser.parse_args(args)
    x(args.xcenter, args.ycenter)

if __name__ == '__main__':
    main(sys.argv[1:])

En supposant que vous l'ayez nommé mytest.py. Pour l'exécuter, vous pouvez faire l'une des choses suivantes à partir de la ligne de commande

python ./mytest.py -x 8
python ./mytest.py -x 8 -y 2
python ./mytest.py 

qui renvoie respectivement

X center: 8.0
Y center: 4

o

X center: 8.0
Y center: 2.0

o

X center: 2
Y center: 4

Ou si vous voulez exécuter à partir d'un autre script de python vous pouvez faire

import mytest
mytest.main(["-x","7","-y","6"]) 

qui renvoie

X center: 7.0
Y center: 6.0

33voto

Aaron Digulla Points 143830

Cela dépend. Si le code principal est protégé par un if comme dans :

if __name__ == '__main__':
    ...main code...

alors non, vous ne pouvez pas faire exécuter cela à Python car vous ne pouvez pas influencer la variable automatique __name__ .

Mais lorsque tout le code est dans une fonction, alors vous pouvez peut-être le faire. Essayez

import myModule

myModule.main()

Cela fonctionne même lorsque le module se protège avec un __all__ .

from myModule import * pourrait ne pas faire main visible pour vous, donc vous devez vraiment importer le module lui-même.

3voto

eguaio Points 23

J'ai eu le même besoin en utilisant argparse aussi. Le truc, c'est que parse_args fonction d'un argparse.ArgumentParser prend implicitement ses arguments par défaut à partir des éléments suivants sys.args . Le contournement, suivant la ligne de Martijn, consiste à rendre cela explicite, de sorte que vous pouvez changer les arguments que vous passez à parse_args comme un désir.

def main(args):
    # some stuff
    parser = argparse.ArgumentParser()
    # some other stuff
    parsed_args = parser.parse_args(args)
    # more stuff with the args

if __name__ == '__main__':
    import sys
    main(sys.argv[1:])

Le point clé est de passer des arguments à parse_args fonction. Plus tard, pour utiliser la fonction main, il suffit de faire comme Martijn le dit.

3voto

Sida Zhou Points 356

La réponse que je cherchais a été donnée ici : Comment utiliser python argparse avec des args autres que sys.argv ?

Si main.py y parse_args() est écrit de cette façon, alors le parsing peut être fait de façon agréable.

# main.py
import argparse
def parse_args():
    parser = argparse.ArgumentParser(description="")
    parser.add_argument('--input', default='my_input.txt')
    return parser

def main(args):
    print(args.input)

if __name__ == "__main__":
    parser = parse_args()
    args = parser.parse_args()
    main(args)

Ensuite, vous pouvez appeler main() et analyser les arguments avec parser.parse_args(['--input', 'foobar.txt']) dans un autre script python :

# temp.py
from main import main, parse_args
parser = parse_args()
args = parser.parse_args([]) # note the square bracket
# to overwrite default, use parser.parse_args(['--input', 'foobar.txt'])
print(args) # Namespace(input='my_input.txt')
main(args)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X