Estoy tratando de acceder a los datos de un módulo desde su __main__.py
.
La estructura es la siguiente:
mymod/ __init__.py __main__.py
Ahora, si __init__.py
una variable en __init__.py
como esta:
__all__ = ['foo'] foo = {'bar': 'baz'}
¿Cómo puedo acceder a foo
desde __main__.py
?
sys.path
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
.
Para agregar mymod
a la ruta se vería algo así (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
Usando el -m
le gustaría:
python -m mymod
Vea esta respuesta para más discusión.
El problema con el que más me encuentro con este tipo de cosas es que a menudo quiero ejecutar el archivo __init__.py
como una secuencia de comandos para probar las características, pero estas no deben ejecutarse al cargar el paquete. Hay una solución útil para las diferentes rutas de ejecución entre python
y python -m
.
$ python -m
ejecuta /__main__.py
. __init__.py
no está cargado. $ python /__init__.py
simplemente ejecuta el script __init__.py
como un script normal. 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 … recurrimos a rutas de importación de rutas absolutas, que pueden causar muchos otros problemas).
Use dos archivos de script para el módulo __main__
:
/ __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 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 el caso de que __init__.py
desde __init__.py
, ya que las estamos recargando en el ámbito local de otro módulo, a pesar de haberlas cargado en __init__.py
ya, pero la carga explícita debe evitar Carga circular. Si vuelve a cargar todo el módulo __init__
en su main.py
, no se cargará como __main__
, por lo que debe ser seguro en lo que respecta a la carga circular.
El módulo __init__
de un paquete actúa como miembros del mismo paquete, por lo que los objetos se importan directamente desde mymod
:
from mymod import foo
O
from . import foo
Si te gusta ser conciso, lee sobre las importaciones relativas . mymod/__main__.py
asegurarse, como siempre, de no invocar el módulo como mymod/__main__.py
, por ejemplo, ya que eso evitará que Python detecte mymod
como un paquete. Es posible que desee mirar en distutils
.
Si ejecuta el módulo con python -m mymod
, el código en __main__.py
podrá importar del rest del módulo sin tener que agregar el módulo a sys.path
.
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 el indicador -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}}