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?

Était-ce utile?

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}}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top