En Python tengo un módulo myModule.py donde defino algunas funciones y un main () , que toma algunos argumentos de línea de comando.
Normalmente llamo a esto main () desde un script bash. Ahora, me gustaría poner todo en un paquete pequeño , así que pensé que tal vez podría convertir mi simple script bash en un script Python y ponerlo en el paquete.
Entonces, ¿cómo llamo realmente a la función main () de myModule.py desde la función main () de MyFormerBashScript.py? ¿Puedo siquiera hacer eso? ¿Cómo le paso algún argumento ?
myModule.main()
. ¿Qué has intentado hasta ahora?subprocess
módulo?Respuestas:
Es solo una función. Importarlo y llamarlo:
import myModule myModule.main()
Si necesita analizar argumentos, tiene dos opciones:
Analizarlos
main()
, pero pasarlossys.argv
como un parámetro (todo el código a continuación en el mismo módulomyModule
):def main(args): # parse arguments using optparse or argparse or what have you if __name__ == '__main__': import sys main(sys.argv[1:])
Ahora puede importar y llamar
myModule.main(['arg1', 'arg2', 'arg3'])
desde otro módulo.Tener
main()
aceptar parámetros que ya son analizadas (de nuevo todo el código en elmyModule
módulo):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)
e importar y llamar a
myModule.main(foovalue, barvalue, baz='ham')
otro lugar y pasar argumentos de Python según sea necesario.El truco aquí es detectar cuándo se está utilizando su módulo como script; cuando ejecuta un archivo de Python como el script principal (
python filename.py
) noimport
se usa ninguna declaración, por lo que Python llama a ese módulo"__main__"
. Pero si ese mismofilename.py
código se trata como un módulo (import filename
), Python lo usa como el nombre del módulo. En ambos casos, la variable__name__
está configurada y la prueba con ella le indica cómo se ejecutó su código.fuente
argparse
, así que cuando llamo al script desde una terminal, lo hago$ python myModule -a input_a -b input_b --parameterC input_c
. ¿Cómo funcionaría desde dentro del código Python? Eso es lo que no pude encontrar con una simple búsqueda.La respuesta de Martijen tiene sentido, pero faltaba algo crucial que puede parecer obvio para los demás, pero que fue difícil de entender para mí.
En la versión donde usa argparse, necesita tener esta línea en el cuerpo principal.
Normalmente, cuando usa argparse solo en un script, solo escribe
y parse_args encuentran los argumentos de la línea de comando. Pero en este caso, la función principal no tiene acceso a los argumentos de la línea de comandos, por lo que debe decirle a argparse cuáles son los argumentos.
Aquí hay un ejemplo
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:])
Suponiendo que nombró a esto mytest.py Para ejecutarlo, puede hacer cualquiera de estos desde la línea de comando
python ./mytest.py -x 8 python ./mytest.py -x 8 -y 2 python ./mytest.py
que regresa respectivamente
X center: 8.0 Y center: 4
o
X center: 8.0 Y center: 2.0
o
X center: 2 Y center: 4
O si desea ejecutar desde otro script de Python, puede hacerlo
import mytest mytest.main(["-x","7","-y","6"])
que regresa
X center: 7.0 Y center: 6.0
fuente
AttributeError: module 'sqlacodegen' has no attribute 'main'
Depende. Si el código principal está protegido por un
if
como en:if __name__ == '__main__': ...main code...
entonces no, no puede hacer que Python ejecute eso porque no puede influir en la variable automática
__name__
.Pero cuando todo el código está en una función, es posible que pueda hacerlo. Tratar
import myModule myModule.main()
Esto funciona incluso cuando el módulo se protege con un
__all__
.from myModule import *
puede que no seamain
visible para usted, por lo que realmente necesita importar el módulo.fuente
import sys; module.main(sys.argv);
__main__
que me ayudó, gracias @AaronDigullaYo también tenía la misma necesidad de usar
argparse
. La cosa esparse_args
función de unaargparse.ArgumentParser
instancia de objeto implícitamente toma sus argumentos por defecto desys.args
. La solución, siguiendo la línea de Martijn, consiste en hacer eso explícito, para que pueda cambiar los argumentos a los que pasaparse_args
como deseo.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:])
El punto clave es pasar argumentos para
parse_args
funcionar. Más tarde, para usar el main, haz lo que te diga Martijn.fuente
La respuesta que estaba buscando fue respondida aquí: ¿Cómo usar python argparse con argumentos distintos de sys.argv?
Si
main.py
yparse_args()
está escrito de esta manera, entonces el análisis se puede hacer muy bien# 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)
Luego puede llamar
main()
y analizar argumentos conparser.parse_args(['--input', 'foobar.txt'])
él en otro script de 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)
fuente
Suponiendo que también está intentando pasar los argumentos de la línea de comandos.
import sys import myModule def main(): # this will just pass all of the system arguments as is myModule.main(*sys.argv) # all the argv but the script name myModule.main(*sys.argv[1:])
fuente
argparse
lugar desys.argv
. ¿Cómo cambiaría en este caso? Además, desde el script externo solo quiero pasar algunos argumentos de entrada que el usuario escribe, mientras que otros argumentos de entrada para el script interno (myModule.py) están codificados por mí.*
desempaqueta una matrizf(a) => f([1,2,3])
frente a lof(*a) => f(1,2,3)
que podría hacer con la misma facilidadmyModule.main(sys.argv[1], "other value", 39)
o lo que sea.