En utilisant les propres objets dans __main__.py du module
Question
Je suis en train d'accéder aux données d'un module à l'intérieur de son __main__.py
.
La structure est la suivante:
mymod/
__init__.py
__main__.py
Maintenant, si j'expose une variable dans __init__.py
comme ceci:
__all__ = ['foo']
foo = {'bar': 'baz'}
Comment puis-je accéder à foo
de __main__.py
?
La solution
Vous devez soit avoir le paquet déjà sys.path
, ajoutez le répertoire contenant mymod
à sys.path
dans __main__.py
, ou utilisez le commutateur -m
.
Pour ajouter mymod
au chemin ressemblerait à quelque chose comme ça (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
En utilisant l'interrupteur -m
souhaite:
python -m mymod
Voir cette réponse pour une discussion plus approfondie.
Autres conseils
La question que je lance dans le plus avec ce genre de chose est que je veux souvent exécuter le fichier __init__.py
comme un script pour tester des fonctionnalités, mais ceux-ci ne doit pas être exécuté lors du chargement du package. Il existe une solution utile pour les différents chemins d'exécution entre python <package>/__init__.py
et python -m <package>
.
-
$ python -m <module>
exécute<package>/__main__.py
.__init__.py
n'est pas chargé. -
$ python <package>/__init__.py
exécute simplement le script__init__.py
comme un script normal.
Le problème
Lorsque nous voulons __init__.py
d'avoir une clause if __name__ == '__main__': ...
que utilise trucs de __main__.py
. Nous ne pouvons pas importer __main__.py
car il sera toujours importer __main__.pyc
du chemin de l'interprète. ( moins ... nous avons recours à l'importation hacks de chemin absolu, ce qui peut causer beaucoup d'autres dégâts).
La solution Une solution:)
Utilisez deux fichiers de script pour le __main__
du module:
<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__'
Les importations main.py
ne sont probablement pas idéal dans le cas que nous courons de __init__.py
, comme nous les rechargeant dans le champ d'application locale d'un autre module, malgré les avoir chargement dans __init__.py
déjà, mais le chargement explicite doivent éviter le chargement circulaire. Si vous chargez à nouveau l'ensemble du module de __init__
dans votre main.py
, il ne sera pas chargé en tant que __main__
, devrait donc être sûr que le chargement jusqu'à circulaire est concerné.
Le module __init__
de un paquet agit comme membres du paquet lui-même , de sorte que les objets sont importés directement de mymod
:
from mymod import foo
ou
from . import foo
si vous voulez être laconique, alors lisez sur importations par rapport . Vous devez vous assurer, comme toujours, que vous ne prononcez pas le module comme mymod/__main__.py
, par exemple, qui empêche Python de détecter mymod
comme un ensemble. Vous pouvez regarder dans distutils
.
Si vous exécutez le module avec python -m mymod
puis code __main__.py
sera en mesure d'importer du reste du module sans avoir à ajouter le module à sys.path
.
structure de répertoire du module se présente comme suit:
py/
__init__.py
__main__.py
__ __ initialisation. 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)
__ __ principale. 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})
Exécuter le module sous forme de script en utilisant le drapeau -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}}