モジュールのデータに内部からアクセスしようとしています__main__.py
。
構造は次のとおりです。
mymod/
__init__.py
__main__.py
ここで、次のように変数を公開すると、次の__init__.py
ようになります。
__all__ = ['foo']
foo = {'bar': 'baz'}
foo
からアクセスするにはどうすればよい__main__.py
ですか?
パッケージがすでににあるか、にsys.path
を含むディレクトリを追加するmymod
かsys.path
、スイッチ__main__.py
を使用する必要があります。-m
パスに追加mymod
するには、次のようになります(in __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__': ...
句が必要な場合。常にインタプリタのパスからインポートされるため、インポートできません。( …絶対パスインポートハックに頼らない限り、他の多くの混乱を引き起こす可能性があります)。__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
。
最初の答えは便利であることがわかりました(つまり、ハッキングsys.path
)がpathlib
、Python 3.4に追加すると、次のコードがはるかに単純でPythonicであることがわかりました。
import sys
from pathlib import Path
# You don't need to .insert(), just append
sys.path.append(str(Path(__file__).parent.parent))
モジュールディレクトリの構造は次のとおりです。
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})
-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}}