python - run - Usar los propios objetos del módulo en__main__.py
que es__ name__ python (5)
Estoy intentando acceder a los datos de un módulo desde dentro de su __main__.py
.
La estructura es la siguiente:
mymod/
__init__.py
__main__.py
Ahora, si __init__.py
una variable en __init__.py
esta manera:
__all__ = [''foo'']
foo = {''bar'': ''baz''}
¿Cómo puedo acceder a foo
desde __main__.py
?
El módulo __init__
de un paquete actúa como miembros del paquete en sí, por lo que los objetos se importan directamente desde mymod
:
from mymod import foo
O
from . import foo
si le gusta ser conciso, lea sobre importaciones relativas . mymod/__main__.py
asegurarse, como siempre, de que no invoque el módulo como mymod/__main__.py
, por ejemplo, ya que eso evitará que Python detecte mymod
como un paquete. Es posible que desee ver en distutils
.
El problema con el que me __init__.py
más con este tipo de cosas es que a menudo quiero ejecutar el archivo __init__.py
como un script para probar las características, pero estas no deben ejecutarse al cargar el paquete. Existe una solución útil para las diferentes rutas de ejecución entre python <package>/__init__.py
y python -m <package>
.
-
$ python -m <module>
ejecuta<package>/__main__.py
.__init__.py
no está cargado. -
$ python <package>/__init__.py
simplemente ejecuta el script__init__.py
como un script normal.
El problema
Cuando queremos que __init__.py
tenga una cláusula if __name__ == ''__main__'': ...
que usa cosas de __main__.py
. No podemos importar __main__.py
porque siempre importará __main__.pyc
de la ruta del intérprete. ( A menos que ... recurramos a los cortes de importación de ruta absoluta, que pueden causar muchos otros problemas).
La solución Una solución :)
Use dos archivos de script para __main__
del módulo:
<package>/
__init__.py
__main__.py
main.py
# __init__.py
# ...
# some code, including module methods and __all__ definitions
__all__ = [''foo'', ''bar'']
bar = {''key'': ''value''}
def foo():
return bar
# ...
if __name__ == ''__main__'':
from main import main
main.main()
# __main__.py
# some code...such as:
import sys
if (len(sys.argv) > 1 and sys.argv[1].lower() == ''option1''):
from main import main()
main(''option1'')
elif (len(sys.argv) > 1 and sys.argv[1].lower() == ''option2''):
from main import main()
main(''option2'')
else:
# do something else?
print ''invalid option. please use "python -m <package> option1|option2"''
# main.py
def main(opt = None):
if opt == ''option1'':
from __init__ import foo
print foo()
elif opt == ''option2'':
from __init__ import bar
print bar.keys()
elif opt is None:
print ''called from __init__''
Las importaciones en main.py
probablemente no sean ideales en caso de que __init__.py
, ya que las estamos recargando en el ámbito local de otro módulo, a pesar de tenerlas __init__.py
en __init__.py
, pero la carga explícita debe evitar carga circular Si vuelve a cargar todo el módulo __init__
en main.py
, no se cargará como __main__
, por lo que debería ser seguro en lo que respecta a la carga circular.
La estructura del directorio del módulo es la siguiente:
py/
__init__.py
__main__.py
__init__.py
#!/usr/bin/python3
#
# __init__.py
#
__all__ = [''foo'']
foo = {''bar'': ''baz''}
info = { "package": __package__,
"name": __name__,
"locals": [x for x in locals().copy()] }
print(info)
__main__.py
#!/usr/bin/python3
#
# __main__.py
#
info = { "package": __package__,
"name": __name__,
"locals": [x for x in locals().copy()] }
print(info)
from . import info as pyinfo
print({"pyinfo: ": pyinfo})
Ejecute el módulo como una secuencia de comandos utilizando la -m
$ python -m py
# the printout from the ''print(info)'' command in __init__.py
{''name'': ''py'', ''locals'': [''__all__'', ''__builtins__'', ''__file__'', ''__package__'', ''__path__'', ''__name__'', ''foo'', ''__doc__''], ''package'': None}
# the printout from the ''print(info)'' command in __main__.py
{''name'': ''__main__'', ''locals'': [''__builtins__'', ''__name__'', ''__file__'', ''__loader__'', ''__doc__'', ''__package__''], ''package'': ''py''}
# the printout from the ''print(pyinfo)'' command in __main__.py
{''pyinfo: '': {''name'': ''py'', ''locals'': [''__all__'', ''__builtins__'', ''__file__'', ''__package__'', ''__path__'', ''__name__'', ''foo'', ''__doc__''], ''package'': None}}
Necesita tener el paquete ya en sys.path
, agregar el directorio que contiene mymod
a sys.path
en __main__.py
, o usar el __main__.py
-m
.
Agregar mymod
a la ruta sería algo como esto (en __main__.py
):
import sys
import os
path = os.path.dirname(sys.modules[__name__].__file__)
path = os.path.join(path, ''..'')
sys.path.insert(0, path)
from myprog import function_you_referenced_from_init_file
El uso del -m
le gustaría:
python -m mymod
Vea esta respuesta para más discusión.
Si ejecuta el módulo con python -m mymod
, el código en __main__.py
podrá importar desde el resto del módulo sin tener que agregar el módulo a sys.path
.