Pythonインタープリタは-m
モジュール「ライブラリモジュールを実行する」オプションモジュール「スクリプトとして」。
この Python コード a.py では:
if __name__ == "__main__":
print __package__
print __name__
私はテストpython -m a
を受けて
"" <-- Empty String
__main__
一方、python a.py
戻り値
None <-- None
__main__
私にとって、これら 2 つの呼び出しは、-m オプションで呼び出されたときに __package__ が None ではないことを除いて同じであるように見えます。
興味深いことに、 を使用すると、 python モジュールをコンパイルして a.pyc を取得するのとpython -m runpy a
同じ結果が得られます。python -m a
これらの呼び出しの (実際的な) 違いは何ですか? それぞれに長所と短所はありますか?
また、David BeazleyのPython Essential Referenceでは次のように説明されています。-m オプションは、メインスクリプトの実行前に__main__ モジュール内で実行されるスクリプトとしてライブラリモジュールを実行します。"。 それはどういう意味ですか?
ベストアンサー1
使用すると-m
コマンドラインフラグPythonはモジュールをインポートしますまたはパッケージフラグを使用しない場合は-m
、指定したファイルは次のように実行されます。ただのスクリプト。
パッケージを実行するときには、この区別が重要になります。次の 2 つには大きな違いがあります。
python foo/bar/baz.py
そして
python -m foo.bar.baz
後者の場合と同様に、がインポートされ、 を開始点としてfoo.bar
相対インポートが正しく機能します。foo.bar
デモ:
$ mkdir -p test/foo/bar
$ touch test/foo/__init__.py
$ touch test/foo/bar/__init__.py
$ cat << EOF > test/foo/bar/baz.py
> if __name__ == "__main__":
> print __package__
> print __name__
>
> EOF
$ PYTHONPATH=test python test/foo/bar/baz.py
None
__main__
$ PYTHONPATH=test python -m foo.bar.baz
foo.bar
__main__
その結果、Pythonはスイッチを使用する際にパッケージを実際に考慮する必要があります-m
。通常のスクリプトではなれパッケージなので__package__
に設定されていますNone
。
しかし、パッケージまたはモジュールを実行すると内部パッケージには-m
少なくとも可能性パッケージの内部にあるため、__package__
変数は文字列値に設定されます。上記のデモでは に設定されていますが'foo.bar'
、パッケージ内にないプレーンなモジュールの場合は空の文字列に設定されます。
については__main__
モジュールPython は、実行中のスクリプトを通常のモジュールと同じようにインポートします。グローバル名前空間を保持するために新しいモジュール オブジェクトが作成され、 に格納されますsys.modules['__main__']
。これが__name__
変数が参照するものであり、その構造のキーとなります。
パッケージの場合は、__main__.py
内部にモジュールを作成し、実行時に実行することができますpython -m package_name
。実際、これが唯一の方法です。できるパッケージをスクリプトとして実行します。
$ PYTHONPATH=test python -m foo.bar
python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed
$ cp test/foo/bar/baz.py test/foo/bar/__main__.py
$ PYTHONPATH=test python -m foo.bar
foo.bar
__main__
したがって、 で実行するためにパッケージに名前を付けると、Python はそのパッケージに含まれるモジュール-m
を探し、それをスクリプトとして実行します。その名前は に設定され、モジュール オブジェクトは に格納されたままになります。__main__
'__main__'
sys.modules['__main__']