__main__.py
内からモジュールのデータにアクセスしようとしています。
構造は次のとおりです。
mymod/
__init__.py
__main__.py
さて、次のように__init__.py
で変数を公開すると:
__all__ = ['foo']
foo = {'bar': 'baz'}
__main__.py
からfoo
にアクセスするにはどうすればよいですか?
パッケージがすでにsys.path
にあるか、mymod
を含むディレクトリをsys.path
の__main__.py
に追加するか、-m
スイッチを使用する必要があります。
パスにmymod
を追加すると、次のようになります(__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
-m
スイッチを使用すると、次のようになります。
python -m mymod
詳細については、 この回答 を参照してください。
この種のことで私が最も遭遇する問題は、機能をテストするためのスクリプトとして__init__.py
ファイルを実行したいことが多いということですが、パッケージをロードするときにこれらを実行しないでください。 python <package>/__init__.py
とpython -m <package>
の間のさまざまな実行パスには便利な回避策があります。
$ python -m <module>
は<package>/__main__.py
を実行します。 __init__.py
がロードされていません。$ python <package>/__init__.py
は、通常のスクリプトのようにスクリプト__init__.py
を実行するだけです。__init__.py
にif __name__ == '__main__': ...
句を持たせたい場合ses__main__.py
のもの。 __main__.py
は、インタプリタのパスから常に__main__.pyc
をインポートするため、インポートできません。 (ただし…絶対パスインポートハックに頼りますが、これは他の多くの混乱を引き起こす可能性があります)。
モジュールの__main__
に2つのスクリプトファイルを使用します。
<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__'
main.py
からのインポートは、__init__.py
に既にロードされているにもかかわらず、別のモジュールのローカルスコープにリロードしているため、__init__.py
から実行している場合はおそらく理想的ではありませんが、明示的なロードでは循環ロードを回避する必要があります。 __init__
モジュール全体をmain.py
に再度ロードすると、__main__
としてロードされないため、循環ロードに関する限り安全である必要があります。
モジュールをpython -m mymod
で実行すると、__main__.py
のコードは、モジュールをsys.path
に追加しなくても、モジュールの残りの部分からインポートできます。