if __name__ == "__main__": は何をするのでしょうか?
if name == "main":` は何をするのでしょうか?
# Threading example
import time, thread
def myfunction(string, sleeptime, lock, *args):
while True:
lock.acquire()
time.sleep(sleeptime)
lock.release()
time.sleep(sleeptime)
if __name__ == "__main__":
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
5496
3
Pythonインタープリタがソースファイルを読み込むときには、必ず2つのことを行います。
__name__
のようないくつかの特別な変数を設定し、次にそのファイルに含まれるすべてのコードを実行します。
この仕組みと、Pythonスクリプトでいつも見られる
__name__
のチェックについての質問との関連を見てみましょう。コードサンプル
インポートとスクリプトがどのように機能するかを調べるために、少し異なるコードサンプルを使ってみましょう。 以下の内容が
foo.py
というファイルの中にあるとします。特別な変数
Python interpeterがソースファイルを読み込むときには、まずいくつかの特殊変数を定義します。ここでは、
__name__
という変数について説明します。あなたのモジュールがメインプログラムの場合。
モジュール(ソースファイル)をメインプログラムとして実行している場合、例えば以下のようになります。
インタープリタは、ハードコードされた文字列
"__main__"
を__name__
変数に代入します、つまり自分のモジュールが他のモジュールにインポートされたとき。
一方で、他のモジュールがメインプログラムで、あなたのモジュールをインポートしているとします。これは、メインプログラムの中に、あるいはメインプログラムがインポートしている他のモジュールの中に、このような文があるということです。
この場合、インタプリタはあなたのモジュールのファイル名である
foo.py
を見て、.py
を取り除き、その文字列をあなたのモジュールの__name__
変数に代入します、つまりモジュールのコードを実行する
特殊変数の設定が終わると、インタプリタはモジュールの全コードを1文ずつ実行します。コードサンプルが表示されている側に別のウィンドウを開いて、この説明を追えるようにしておくとよいでしょう。
常に。
1.文字列
"before import"
(引用符なし)を表示します。2.2.
math
モジュールをロードしてmath
という変数に代入します。これは、import math
を以下のように置き換えることと同じです(__import__
は Python の低レベル関数で、文字列を受け取って実際のインポートを実行することに注意してください)。3.文字列
"before functionA"
を表示します。4.def
ブロックを実行して、関数オブジェクトを作成し、その関数オブジェクトを
functionA`という変数に代入します。5.文字列
"before functionB"
を表示します。6.6. 2番目の
def
ブロックが実行され、別の関数オブジェクトが作成され、それがfunctionB
という変数に代入されます。7.文字列
"before __name__ guard"
を表示します。あなたのモジュールがメインプログラムの場合のみ。
8.あなたのモジュールがメインプログラムの場合、
__name__
が確かに"__main__"
に設定されていることを確認し、2つの関数を呼び出して、文字列"Function A"
と"Function B 10.0"
を表示しています。あなたのモジュールが他のモジュールからインポートされたときのみ。
8.(instead) あなたのモジュールがメインプログラムではなく、他のモジュールにインポートされていた場合、
__name__
は"__main__"
ではなく"foo"
となり、if
文の本文はスキップされます。常に。
9.どちらの状況でも
"after __name__ guard"
という文字列が表示されます。まとめ
要約すると、2つのケースで何が表示されるかを示します。
なぜこのような仕組みになっているのか?
なぜこんなことをしたいのかと思うかもしれません。 さて、
.py
ファイルを書いて、他のプログラムやモジュールからモジュールとして利用したり、メインプログラムとして実行したりしたい場合があります。 例を挙げてみましょう。あなたのモジュールはライブラリですが、ユニットテストやデモを実行するスクリプトモードを持ちたいとします。
あなたのモジュールは、メインプログラムとしてのみ使用されますが、いくつかのユニットテストを持っており、テストフレームワークは、あなたのスクリプトのような
.py
ファイルをインポートし、特別なテスト関数を実行することで動作します。モジュールをインポートしているからといって、スクリプトを実行しようとはしないでほしいのです。あなたのモジュールは、主にメインプログラムとして使用されますが、上級ユーザーのためにプログラマーフレンドリーなAPIも提供しています。
これらの例に限らず、Pythonでスクリプトを実行することは、いくつかの魔法の変数を設定し、スクリプトをインポートするだけであることはエレガントです。スクリプトの "実行 "は、スクリプトのモジュールをインポートすることによる副次的な効果です。
Food for Thought
質問です。複数の
__name__
チェックブロックを持つことはできますか? 答え:そうするのはおかしいですが、言語はあなたを止めません。次のようなものが
foo2.py
にあるとします。 コマンドラインでpython foo2.py
と言ったらどうなりますか?なぜですか?foo3.py
で__name__
のチェックを外したらどうなるか考えてみましょう。スクリプトをPythonインタープリターにコマンドとして渡して実行する場合。
インデントレベル 0 のコードはすべて実行されます。 定義されている関数やクラスは、まあ、定義されていますが、そのコードは何も実行されません。 他の言語と違って、自動的に実行される
main()
関数はありません。main()
関数は暗黙のうちにトップレベルのすべてのコードです。この場合、トップレベルのコードとは
if
ブロックのことです。 nameは組み込み変数で、現在のモジュールの名前として評価されます。 しかし、モジュールが直接実行されている場合(上記の
myscript.pyのように)、代わりに
nameには文字列
"main"` が設定されます。 したがって、スクリプトが直接実行されているのか、何か他のものからインポートされているのかをテストするには、次のようにします。スクリプトが他のモジュールにインポートされている場合、その様々な関数やクラスの定義がインポートされ、トップレベルのコードが実行されますが、上記の
if
節の then-body にあるコードは、条件が満たされていないため実行されません。基本的な例として、次の2つのスクリプトを考えてみましょう。さて、インタプリタを次のように起動すると
という出力が得られます。
代わりに
two.py
を実行した場合。次のようになります。
このように、モジュール
one
がロードされると、その__name__
は"main__"
ではなく"one"
になります。if name == "main"
は、スクリプトがコマンドラインから
python myscript.py` のようなコマンドを使って実行されたときに実行される部分です。