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



Answers

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

python myscript.py

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

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

if __name__ == "__main__":
    ...

スクリプトが別のモジュールにインポートされている場合、そのさまざまな関数とクラス定義がインポートされ、その最上位コードが実行されますが、上記のif節の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__"__main__"ではなく"one"に等しくなります。

Question

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))



システム(Pythonインタプリタ)がソースファイル(モジュール)用に用意している変数はたくさんあります。 いつでも必要なときに値を取得できるので、__ name__変数/属性に注目しましょう:

Pythonがソースコードファイルを読み込むと、Pythonはそこにあるすべてのコードを実行します。 (ファイルに定義されているすべてのメソッドと関数を呼び出すわけではありませんが、定義しています。)

インタプリタがソースコードファイルを実行する前に、そのファイルにはいくつかの特殊変数が定義されています。 __name__はPythonが各ソースコードファイルに対して自動的に定義する特別な変数の1つです。

Pythonがこのソースコードファイルをメインプログラム(つまり実行しているファイル)としてロードしている場合、このファイルの特別な__name__変数に"__main__"という値を設定します。

これが別のモジュールからインポートされている場合、 __name__はそのモジュールの名前に設定されます。

ですから、あなたの例では、

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))

コードブロック:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

モジュールを直接実行した場合にのみ実行されます。 その特定のインスタンスで__name__の値が " main "に等しくないため、別のモジュールが呼び出し/インポートしている場合、コードブロックは実行されません。

これが助けてくれるといいですね。




ファイルをインポート可能なモジュールと同様にスクリプトとして使用することができます

fibo.py(fiboという名前のモジュール)

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

リファレンス: https://docs.python.org/3.5/tutorial/modules.html : https://docs.python.org/3.5/tutorial/modules.html




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

ファイル "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を実行するxy.pyimport abimport abます。 import文はインポート時にすぐにモジュールを実行するので、 abの演算はxyの残りの部分より前に実行されます。 ab終了すると、 xy続けます。

インタプリタは、どのスクリプトが__name__実行されているかを追跡します。 スクリプトを実行すると、名前を付けてもインタープリタはそれを"__main__"と呼び、外部スクリプトを実行した後に返されるマスタースクリプトまたは「ホーム」スクリプトにします。 この"__main__"スクリプトから呼び出される他のスクリプトには、そのファイル名が__name__ == "ab.py" (例えば、 __name__ == "ab.py" )として割り当てられます。 したがって、 if __name__ == "__main__":の行は、最初に実行された 'home'スクリプトを解釈/解析しているのか、別の(外部の)スクリプトに一時的に侵入しているのかを判断するインタープリタのテストです。 これによりプログラマは、直接実行された場合と外部で呼び出された場合のスクリプトの動作が異なるように柔軟に対応できます。

上記のコードを踏んで、何が起きているのかを理解して、字下げのない行とスクリプトに表示される順序に焦点を当ててみましょう。 ファンクションブロックまたはdefブロックは、呼び出されるまでは何もしません。 通訳者が自分自身に混乱していると言うかもしれないもの:

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

下の2行は、「これがmainスクリプトまたはホームスクリプトの場合、 main() 」という関数を実行します。 そのため、 def main(): block up topが表示されます。これにはスクリプトの機能のメインフローが含まれています。

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

先ほどインポート・ステートメントについて述べたことを思い出してください。 モジュールをインポートするとき、モジュールは「認識」するだけでなく、それ以上の指示を待つことになります。実際には、スクリプトに含まれるすべての実行可能な操作が実行されます。 したがって、スクリプトの中身をmain()関数に入れると、それを隔離して隔離するので、別のスクリプトでインポートしたときにすぐに実行されることはありません。

ここでも例外はありますが、通常はmain()は通常外部から呼び出されません。 だから、もう一つのことが不思議に思えるかもしれません。main main()呼び出さないと、なぜスクリプトを呼び出すのですか? これは、ファイル内の残りのコードとは独立して実行できるように構築されたスタンドアロン関数を使用してスクリプトを構成する人が多いためです。 それらは後でスクリプト本体のどこかで呼び出されます。 それは私にこれをもたらします:

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

はい、そうです。 これらの別々の関数main()関数内に含まれていないインラインスクリプトから呼び出すことできます。 あなたが必要とするものを正確に実行するインラインスクリプトを作成することに慣れていれば、もう一度その操作が必要になったらもう一度理解しようとします。あなたのコードにこの種の内部構造は慣れていません。なぜなら、構築するのがより複雑で、読むのが直感的ではないからです。 しかし、それはおそらく外部から呼び出される関数を持つことができないスクリプトです。なぜなら、そうした場合、変数の計算と割り当てがすぐに開始されるからです。 また、関数を再利用しようとしている場合、新しいスクリプトは古い変数と密接に関連しており、矛盾する変数が存在する可能性があります。

独立した関数を分割する際に、前の作業を別のスクリプトに呼び出すことで、以前の作業を再利用することができます。 例えば、 "example.py"は "xy.py"から "x"関数を利用して "xy.py"を呼び出してx()を呼び出すかもしれません。 (おそらく、与えられた文字列の3番目の単語を大文字にしているかもしれません;数字のリストから数え切れない配列を作成し、それらを二乗するか、または3Dサーフェスをデトロイズすることです。

[さて、 このスレッドには@kindallの回答が含まれています。 これは最終的に私が理解するのを助けました。 残念なことに、これは私が間違いであると思うこの複製とマークされています。]




if __name__ == '__main__'について何かを説明する前にif __name__ == '__main__' __name__が何であるか、そして何をするのかを理解することが重要__name__

__name__とは何ですか?

__name__はDunderAliasであり、グローバル変数(モジュールからアクセス可能)と考えることができ、グローバルと同様に動作します。

これは、 type(__name__)<class 'str'>を生成するtype(__name__)によって示される文字列(上記のようにグローバル)であり、 Python 3Python 2の両方のバージョンの組み込み標準です。

場所:

これはスクリプトでのみ使用することはできませんが、インタプリタとモジュール/パッケージの両方にもあります。

通訳:

>>> print(__name__)
__main__
>>>

スクリプト:

test_file.py

print(__name__)

__main__結果

モジュールまたはパッケージ:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

somefile結果

パッケージまたはモジュールで使用される場合、 __name__はファイルの名前になります。 実際のモジュールまたはパッケージパスのパスは指定されていませんが、独自のDunderAlias __file__があります。

メインファイル(またはプログラム)のどこにある__name__常に __main__ 返し、モジュール/パッケージ、または他のPythonスクリプトから実行されているものであれば、ファイルの名前を返しますそこから生まれたのです。

練習:

変数は値上書きすることできることを意味します( "can"は "should"を意味しません) __name__の値を上書きすると、読みやすくなりません。 何らかの理由でそれをしないでください。 変数が必要な場合は、新しい変数を定義します。

__name__の値は__main__またはファイル名であると常に仮定されています。 もう一度このデフォルト値を変更すると、それが良い結果をもたらすという混乱が生じ、問題をさらに深刻化させます。

例:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

スクリプトにif __name__ == '__main__'を含めることは一般的には良い方法if __name__ == '__main__'

if __name__ == '__main__'今すぐ答えてください:

__name__の動作がより明確になることがわかりました。

ifは、指定された値がtrueの場合に実行されるコードブロックを含むフロー制御文です。 __name__は、 __main__か、それがインポートされたファイル名のどちらかを取ることができます。

つまり、 __name____main__等しい場合、ファイルはメインファイルであり、スクリプトにインポートされたモジュールまたはパッケージではなく、実際に実行されている(またはインタプリタである)必要があります。

実際に__name____main__の値をとった場合、そのコードブロックにあるものが実行されます。

これは、実行中のファイルがメインファイル(またはインタプリタから直接実行しているファイル)の場合、その条件を実行する必要があることを示しています。 それがパッケージであれば、そうでなければならず、値は__main__はありません。

モジュール:

__name__は、モジュールで使用してモジュールの名前を定義することもできます

バリアント:

__name__で他の、あまり一般的ではないが有用なことを行うことも可能__name__ 。ここではいくつかを示します:

ファイルがモジュールまたはパッケージの場合にのみ実行:

if __name__ != '__main__':
    # Do some useful things 

ファイルがメインの場合は1つの条件を実行し、そうでない場合は別の条件を実行します。

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

ライブラリを精巧に使用することなく、パッケージやモジュール上で実行可能なヘルプ関数/ユーティリティを提供することもできます。

また、モジュールをコマンドラインからメインスクリプトとして実行することもでき、非常に便利です。




if __name__ == "__main__":if __name__ == "__main__":ますか?

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

しかし、唯一の特別なケースとして、mycode.pyのように、Pythonのプロセスを実行するにあたって:

python mycode.py

そうでなければ匿名のグローバル名前空間には、その__name__'__main__'という値が割り当てられます。

したがって、 最終ラインを含め

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

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

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

import mycode
# ... any amount of other code
mycode.main()



if __name__ == "__main__":基本的にはトップレベルのスクリプト環境で、( '私は最初に実行する優先度が高い')インタプリタを指定します。

'__main__'は、トップレベルコードが実行されるスコープの名前'__main__' 。 モジュールの__name__は、標準入力、スクリプト、または対話型プロンプトから読み取ったときに'__main__'と等しく設定されます。

if __name__ == "__main__":
    # execute only if run as a script
    main()



if __name__ == "__main__":
    main()

Pythonスクリプトの__name__属性が"__main__"であるかどうかをチェックします。 言い換えれば、プログラム自体が実行された場合、属性は__main__になるので、プログラムが実行されます(この場合はmain()関数)。

しかし、あなたのPythonスクリプトがモジュールによって使用されているifは、 if文の外側のコードが実行されるので、プログラムがモジュールとして使用されているかどうかをチェックするためにif \__name__ == "\__main__"したがって、コードを実行するかどうかを決定します。




Pythonを対話的に実行すると、ローカルの__name__変数に__main__という値が割り当てられます。 同様に、Pythonモジュールをコマンドラインから別のモジュールにインポートするのではなく、そのモジュールの実際の名前ではなく、 __name__属性に__main__という値を割り当てます。 このようにして、モジュールは独自の__name__値を調べて、別のプログラムのサポートとして、またはコマンドラインから実行されるメインアプリケーションとして、どのように使用されているかを判断することができます。 したがって、以下のイディオムはPythonモジュールではよく使用されます。

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.



if name == ' main ':

私たちは__name__ == '__main__' :かなり頻繁に見ます。

モジュールがインポートされているかどうかをチェックします。

言い換えれば、 ifブロック内のコードは、コードが直接実行されたときにのみ実行されます。 ここではdirectly not imported directly意味します。

modueの名前を表示する簡単なコードを使って何が行われているかを見てみましょう:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

python test.pyで直接コードを実行すると、モジュール名は__main__ます。

call test()
test module name=__main__



if __name__ == "__main__":は何ですか?

基本を概説するには:

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

  • したがって、 ifブロックの下のコードは、モジュールがプログラムのエントリポイントである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()

この慣用句は、 __main__モジュールの説明のPythonドキュメントにもあります。 そのテキストの状態:

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

if __name__ == '__main__':
    main()



Related