1. ホーム
  2. python

[解決済み] Pythonコードの実行に-mオプションをつけるかどうか

2022-04-26 18:04:37

質問

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 -m runpy a と同じになります。 python -m a を、pythonモジュールをコンパイルしてa.pycを得ました。

これらの呼び出しの(実用的な)違いは何でしょうか?また、その長所と短所は何ですか?

また、David BeazleyのPython Essential Referenceでは、"と説明されています。 mオプションは、メインスクリプトの実行前に__main__モジュールの内部で実行されるスクリプトとしてライブラリモジュールを実行します。 となります。どういう意味でしょうか?

どのように解決するのですか?

を使用する場合 -m コマンドラインフラグ Python がモジュールをインポートする場合、Python は またはパッケージ を実行し、それをスクリプトとして実行します。を使用しない場合は -m フラグを使用すると、指定したファイルは 単なるスクリプト .

この区別は、パッケージを実行しようとするときに重要です。大きな違いがあります。

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__

そのため、実行するパッケージの名前を -m を探すと、Pythonは __main__ モジュールが含まれ、それをスクリプトとして実行します。その際、名前はまだ '__main__' に格納され、モジュールオブジェクトはまだ sys.modules['__main__'] .