__name__ == "__main__"の場合はどうなりますか?

2009年01月07日に質問されました。  ·  閲覧回数 3.2M回  ·  ソース

Devoted picture
2009年01月07日

次のコードを考えると、 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))

回答

Mr Fooz picture
2009年01月07日
7128

Pythonインタープリターがソースファイルを読み取るときは常に、次の2つのことを行います。

  • __name__ようないくつかの特別な変数を設定し、次に

  • ファイル内にあるすべてのコードを実行します。

これがどのように機能し、Pythonスクリプトで常に見られる__name__チェックに関する質問とどのように関連するかを見てみましょう。

コードサンプル

少し異なるコードサンプルを使用して、インポートとスクリプトがどのように機能するかを調べてみましょう。 以下がfoo.pyというファイルにあるとします。

# Suppose this is foo.py.

print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

特別な変数

Pythonインタープリターがソースファイルを読み取るとき、最初にいくつかの特別な変数を定義します。 この場合、 __name__変数が重要です。

モジュールがメインプログラムの場合

モジュール(ソースファイル)をメインプログラムとして実行している場合、例:

python foo.py

インタプリタは、ハードコードされた文字列"__main__"__name__変数に割り当てます。

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

モジュールが別のモジュールによってインポートされたとき

一方、他のモジュールがメインプログラムであり、モジュールをインポートするとします。 これは、メインプログラム、またはメインプログラムがインポートする他のモジュールに次のようなステートメントがあることを意味します。

# Suppose this is in some other main program.
import foo

通訳は、あなたのために検索しますfoo.py (他のいくつかの亜種を探しに加えて)ファイル、およびそのモジュールを実行する前に、それは名前が割り当てられます"foo"するimport文から__name__変数、つまり

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

モジュールのコードの実行

特別な変数が設定された後、インタプリタはモジュール内のすべてのコードを一度に1つのステートメントで実行します。 この説明に従うことができるように、コードサンプルの横にある別のウィンドウを開くことをお勧めします。

常に

  1. 文字列"before import" (引用符なし)を出力します。

  2. mathモジュールをロードし、それをmathという変数に割り当てます。 これは、 import mathを次のように置き換えることと同じです( __import__は、文字列を受け取り、実際のインポートをトリガーするPythonの低レベル関数であることに注意してください)。

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. 文字列"before functionA"ます。

  2. defブロックを実行し、関数オブジェクトを作成してから、その関数オブジェクトをfunctionAという変数に割り当てます。

  3. 文字列"before functionB"ます。

  4. 2番目のdefブロックを実行し、別の関数オブジェクトを作成して、それをfunctionBという変数に割り当てます。

  5. 文字列"before __name__ guard"ます。

モジュールがメインプログラムの場合のみ

  1. モジュールがメインプログラムの場合、 __name__が実際に"__main__"に設定されていることがわかり、2つの関数を呼び出して、文字列"Function A""Function B 10.0"

モジュールが別のモジュールによってインポートされた場合のみ

  1. 代わりに)モジュールがメインプログラムではなく、別のプログラムによってインポートされた場合、 __name__"foo"ではなく"__main__"になり、の本文はスキップされます。 ifステートメント。

常に

  1. どちらの状況でも、文字列"after __name__ guard"れます。

概要

要約すると、2つの場合に印刷されるものは次のとおりです。

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

なぜこのように機能するのですか?

なぜ誰もがこれを欲しがるのか不思議に思うかもしれません。 他のプログラムやモジュールでモジュールとして使用でき、メインプログラム自体としても実行できる.pyファイルを作成したい場合があります。 例:

  • モジュールはライブラリですが、単体テストまたはデモを実行するスクリプトモードが必要です。

  • モジュールはメインプログラムとしてのみ使用されますが、いくつかの単体テストがあり、テストフレームワークは、スクリプトのような.pyファイルをインポートし、特別なテスト関数を実行することで機能します。 モジュールをインポートしているという理由だけでスクリプトを実行しようとしないでください。

  • モジュールは主にメインプログラムとして使用されますが、上級ユーザー向けにプログラマー向けのAPIも提供します。

これらの例を超えて、Pythonでスクリプトを実行することは、いくつかの魔法の変数を設定し、スクリプトをインポートするだけであることはエレガントです。 スクリプトの「実行」は、スクリプトのモジュールをインポートすることの副作用です。

思考の糧

  • 質問:複数の__name__チェックブロックを使用できますか? 回答:そうするのは奇妙ですが、言語はあなたを止めません。

  • 以下がfoo2.pyます。 コマンドラインでpython foo2.pyと言うとどうなりますか? どうして?

# Suppose this is foo2.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
      
  • ここで、 foo3.py__name__チェックを削除するとどうなるかを理解します。
# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • スクリプトとして使用すると、これは何をしますか? モジュールとしてインポートする場合?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")
    
print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")
Adam Rosenfield picture
2009年01月07日
1884

スクリプトをコマンドとしてPythonインタープリターに渡して実行すると、

python myscript.py

インデントレベル0のすべてのコードが実行されます。 定義されている関数とクラスは、まあ、定義されていますが、それらのコードはどれも実行されません。 他の言語とは異なり、自動的に実行されるmain()関数はありません。 main()関数は、暗黙的にトップレベルのすべてのコードです。

この場合、最上位のコードはifブロックです。 __name__は、現在のモジュールの名前に評価される組み込み変数です。 ただし、モジュールが直接実行されている場合(上記のmyscript.pyように)、代わりに__name__が文字列"__main__"設定されます。 したがって、テストすることで、スクリプトが直接実行されているのか、他の何かによってインポートされているのかをテストできます。

if __name__ == "__main__":
    ...

スクリプトを別のモジュールにインポートする場合、そのさまざまな関数とクラスの定義がインポートされ、その最上位のコードが実行されますが、上記のif句のthen-bodyのコードは実行されません。条件が満たされていないため、実行されます。 基本的な例として、次の2つのスクリプトについて考えてみます。

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

さて、インタプリタを次のように呼び出すと

python one.py

出力は次のようになります

top-level in one.py
one.py is being run directly

代わりにtwo.pyを実行する場合:

python two.py

あなたが得る

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

このように、モジュールone 、その、ロードされる__name__等しい"one"の代わりに"__main__"

pi. picture
2009年01月07日
745

__name__変数(imho)の最も簡単な説明は次のとおりです。

以下のファイルを作成します。

# a.py
import b

そして

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

それらを実行すると、次の出力が得られます。

$ python a.py
Hello World from b!

ご覧のとおり、モジュールがインポートされると、Pythonはこのモジュールのglobals()['__name__']をモジュールの名前に設定します。 また、インポート時に、モジュール内のすべてのコードが実行されます。 ifステートメントはFalse評価されるため、この部分は実行されません。

$ python b.py
Hello World from __main__!
Hello World again from __main__!

ご覧のとおり、ファイルが実行されると、Pythonはこのファイルのglobals()['__name__']"__main__"ます。 今回は、 ifステートメントがTrueと評価され、実行されています。

Aaron Hall picture
2013年11月23日
522

if __name__ == "__main__":は何をしますか?

基本の概要を説明します。

  • プログラムへのエントリポイントであるモジュール内のグローバル変数__name__は、 '__main__'です。 それ以外の場合は、モジュールをインポートする際の名前です。

  • したがって、 ifブロックの下のコードは、モジュールがプログラムへのエントリポイントである場合にのみ実行されます。

  • これにより、インポート時に下のコードブロックを実行しなくても、モジュール内のコードを他のモジュールからインポートできます。


なぜ私たちはこれが必要なのですか?

コードの開発とテスト

モジュールとして使用するように設計されたPythonスクリプトを作成しているとします。

def do_important():
    """This function does something very important"""

この関数の呼び出しを下部に追加することで、モジュールをテストできます。

do_important()

そしてそれを(コマンドプロンプトで)次のようなもので実行します:

~$ python important.py

問題

ただし、モジュールを別のスクリプトにインポートする場合は、次のようにします。

import important

インポート時にdo_important関数が呼び出されるので、おそらく下部にある関数呼び出しdo_important()コメントアウトします。

# do_important() # I must remember to uncomment to execute this!

次に、テスト関数呼び出しをコメントアウトしたかどうかを覚えておく必要があります。 そして、この余分な複雑さは、忘れがちであり、開発プロセスをより面倒にすることを意味します。

より良い方法

__name__変数は、Pythonインタープリターが現在存在する場所にある名前空間を指します。

インポートされたモジュール内では、それはそのモジュールの名前です。

ただし、プライマリモジュール(またはインタラクティブなPythonセッション、つまりインタープリターのRead、Eval、Print Loop、またはREPL)内では、 "__main__"からすべてを実行しています。

したがって、実行する前に確認すると、次のようになります。

if __name__ == "__main__":
    do_important()

上記の場合、コードは、プライマリモジュールとして実行しているとき(または意図的に別のスクリプトから呼び出しているとき)にのみ実行されます。

さらに良い方法

ただし、これを改善するためのPythonの方法があります。

モジュールの外部からこのビジネスプロセスを実行したい場合はどうなりますか?

このような関数で開発およびテストするときに実行するコードを配置し、その直後に'__main__'チェックする場合:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

これで、モジュールをプライマリモジュールとして実行した場合に実行される、モジュールの最後の最終関数ができました。

これにより、 main関数を実行せずに、モジュールとその関数およびクラスを他のスクリプトにインポートできます。また、別の'__main__'から実行するときに、モジュール(およびその関数とクラス)を呼び出すことができます。

import important
important.main()

このイディオムは、Pythonのドキュメントの__main__モジュールの説明にも記載されています。 そのテキストは次のように述べています。

このモジュールは、インタプリタのメインプログラムが実行される(それ以外の場合は匿名の)スコープを表します。コマンドは、標準入力、スクリプトファイル、または対話型プロンプトのいずれかから読み取られます。 慣用的な「条件付きスクリプト」スタンザによってスクリプトが実行されるのは、この環境です。

if __name__ == '__main__':
    main()
Harley Holcombe picture
2009年01月07日
130

if __name__ == "__main__"は、 python myscript.pyようなコマンドを使用して、(たとえば)コマンドラインからスクリプトを実行するときに実行される部分です。

Aaron Hall picture
2014年10月15日
84

if __name__ == "__main__":は何をしますか?

__name__は、すべての名前空間に存在するグローバル変数(Pythonでは、グローバルは実際にはモジュールレベルを意味しstrタイプとして)。

ただし、唯一の特殊なケースとして、mycode.pyのように、実行するPythonプロセスでは次のようになります。

python mycode.py

それ以外の場合は匿名のグローバル名前空間には、 '__main__'の値がその__name__割り当てられます。

したがって、最終行を含める

if __name__ == '__main__':
    main()
  • mycode.pyスクリプトの最後に、
  • Pythonプロセスによって実行されるプライマリのエントリポイントモジュールである場合、

スクリプトの一意に定義されたmain関数が実行されます。

この構成を使用するもう1つの利点は、コードをモジュールとして別のスクリプトにインポートし、プログラムが次のように決定した場合にmain関数を実行することもできます。

import mycode
# ... any amount of other code
mycode.main()
joechoj picture
2016年09月29日
73

問題のコードの仕組みである「方法」については、さまざまな見方がありますが、「なぜ」を理解するまで、私にとっては意味がありませんでした。 これは、新しいプログラマーにとって特に役立つはずです。

ファイル「ab.py」を取得します。

def a():
    print('A function in ab file');
a()

そして2番目のファイル「xy.py」:

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

このコードは実際に何をしているのですか?

xy.pyを実行すると、 import abます。 importステートメントは、インポート時にモジュールをすぐに実行するため、 abの操作は、残りのxyの前に実行されます。 abで終了すると、 xyで続行されます。

インタプリタは、 __name__実行されているスクリプトを追跡します。 スクリプトを実行すると(名前に関係なく)、インタープリターはスクリプトを"__main__"と呼び、外部スクリプトの実行後に返されるマスターまたは「ホーム」スクリプトにします。

この"__main__"スクリプトから呼び出される他のスクリプトには、ファイル名が__name__として割り当てられます(例: __name__ == "ab.py" )。 したがって、行if __name__ == "__main__":は、最初に実行された「ホーム」スクリプトを解釈/解析しているのか、それとも一時的に別の(外部)スクリプトを覗いているのかを判断するためのインタプリタのテストです。 これにより、プログラマーは、スクリプトを直接実行する場合と外部から呼び出す場合で、スクリプトの動作を変えることができます。

上記のコードをステップスルーして、何が起こっているのかを理解しましょう。最初に、インデントされていない行と、スクリプトに表示される順序に焦点を当てます。 関数(またはdef )ブロックは、呼び出されるまでそれ自体では何も実行しないことに注意してください。 通訳が自分自身につぶやいた場合に言うかもしれないこと:

  • xy.pyを「ホーム」ファイルとして開きます。 __name__変数で"__main__"と呼びます。
  • __name__ == "ab.py"ファイルをインポートして開きます。
  • ああ、関数。 私はそれを覚えています。
  • わかりました、関数a() ; 私はちょうどそれを学びました。 印刷 ' abファイル内
  • ファイルの終わり; "__main__"戻る!
  • ああ、関数。 私はそれを覚えています。
  • もう1つ。
  • 関数x() ; わかりました、印刷 '周辺タスク:他のプロジェクトで役立つかもしれません'。
  • これは何ですか? ifステートメント。 条件が満たされている(変数__name__"__main__"設定されている)ので、 main()関数を入力して、 ' main関数を出力します。ここにアクションは'です。

下の2行は、「これが"__main__"または 'home'スクリプトの場合、 main()という関数を実行する」という意味です。 そのため、スクリプトの機能のメインフローを含むdef main():ブロックが上部に表示されます。

なぜこれを実装するのですか?

インポートステートメントについて前に言ったことを覚えていますか? モジュールをインポートすると、モジュールは単に「認識」して次の命令を待つだけでなく、実際にはスクリプトに含まれるすべての実行可能操作を実行します。 したがって、スクリプトの要点をmain()関数に入れると、スクリプトが効果的に隔離され、別のスクリプトによってインポートされたときにすぐに実行されないように分離されます。

繰り返しになりますが、例外はありますが、一般的な方法では、 main()は通常外部から呼び出されません。 したがって、もう1つ疑問に思われるかもしれません。 main()を呼び出さないのに、なぜスクリプトをまったく呼び出さないのでしょうか。 これは、多くの人が、ファイル内の残りのコードから独立して実行されるように構築されたスタンドアロン関数を使用してスクリプトを構成しているためです。 その後、スクリプトの本文の別の場所で呼び出されます。 これは私にこれをもたらします:

しかし、コードはそれなしで動作します

はい、そうです。 これらの個別の関数main()関数内に含まれていないインラインスクリプトから呼び出すこと

しかし、それはおそらく外部から関数を呼び出すことができないスクリプトです。そうすると、すぐに変数の計算と割り当てが開始されるためです。 また、関数を再利用しようとしている場合、新しいスクリプトは古いスクリプトと十分に密接に関連しているため、変数が競合する可能性があります。

独立した関数を分割すると、それらを別のスクリプトに呼び出すことで、以前の作業を再利用できるようになります。 たとえば、「example.py」は「xy.py」をインポートし、「xy.py」の「x」関数を使用してx()を呼び出す場合があります。 (多分それは与えられたテキスト文字列の3番目の単語を大文字にすること;数のリストからNumPy配列を作成してそれらを二乗すること;または3D表面をトレンド除去することです。可能性は無限です。)

(余談ですが、この質問には@kindallによる回答が含まれており、最終的に理解するのに役立ちました。理由ではなく、方法です。残念ながら、これの複製としてマークされています。これは間違いだと思います。)

Nabeel Ahmed picture
2013年04月03日
53

モジュール( M.py )に、メイン(インポートされていない)として実行されるときに実行したい特定のステートメントがある場合、それらのステートメント(テストケース、印刷ステートメント)をこのif下に配置できます。

デフォルトのように(モジュールがメインとして実行され、インポートされていない場合)、 __name__変数は"__main__"に設定され、インポートされると、 __name__変数は異なる値を取得します値、おそらくモジュールの名前( 'M' )。 これは、モジュールのさまざまなバリアントを一緒に実行し、それらの特定の入力ステートメントと出力ステートメントを分離する場合や、テストケースがある場合に役立ちます。

つまり、この ' if __name__ == "main" 'ブロックを使用して、モジュールのインポート時に(特定の)コードが実行されないようにします。

redbandit picture
2016年10月15日
46

簡単に言うと、 __name__は、スクリプトがメインモジュールとして実行されているのか、インポートされたモジュールとして実行されているのかを定義する、スクリプトごとに定義された変数です。

したがって、2つのスクリプトがある場合。

#script1.py
print "Script 1's name: {}".format(__name__)

そして

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

script1の実行からの出力は次のとおりです。

Script 1's name: __main__

そして、script2の実行からの出力は次のとおりです。

Script1's name is script1
Script 2's name: __main__

ご覧のとおり、 __name__は、どのコードが「メイン」モジュールであるかを示しています。 これは素晴らしいことです。コードを書くだけで、C / C ++のように構造上の問題を心配する必要がないためです。ファイルが「メイン」関数を実装していない場合、実行可能ファイルとしてコンパイルできません。実装している場合は、その後、ライブラリとして使用することはできません。

何か素晴らしいことをするPythonスクリプトを書いて、他の目的に役立つ関数のボートロードを実装するとします。 それらを使用したい場合は、スクリプトをインポートして、プログラムを実行せずに使用できます(コードがif __name__ == "__main__":コンテキスト内でのみ実行される場合)。 一方、C / C ++では、これらの部分を別のモジュールに分割して、ファイルを含める必要があります。 以下の状況を想像してください。

Complicated importing in C

矢印はインポートリンクです。 それぞれが前のモジュールコードを含めようとしている3つのモジュールには、6つのファイル(9つ、実装ファイルを数える)と5つのリンクがあります。 これにより、特にライブラリとしてコンパイルされない限り、他のコードをCプロジェクトに含めることが困難になります。 Python用に想像してみてください。

Elegant importing in Python

モジュールを作成し、誰かがコードを使用したい場合は、それをインポートするだけで、 __name__変数は、プログラムの実行可能部分をライブラリ部分から分離するのに役立ちます。

Alisa picture
2015年01月21日
42

より抽象的な方法で答えを見てみましょう:

このコードがx.pyます。

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

ブロックAとBは、 x.pyを実行しているときに実行されます。

ただし、別のモジュール、たとえばy.pyを実行しているときは、ブロックA(Bではなく)だけが実行されます。このモジュールでは、 x.pyがインポートされ、そこからコードが実行されます( x.pyy.pyから呼び出されます)。