python __name__用法 '__main__' - 如果__name__ ==“__ main__”:怎么办?




14 Answers

当Python解释器读取源文件时,它会执行其中的所有代码。

在执行代码之前,它将定义一些特殊变量。 例如,如果Python解释器将该模块(源文件)作为主程序运行,则它将特殊的__name__变量设置为具有值"__main__" 。 如果从另一个模块导入此文件,则__name__将设置为模块的名称。

在你的脚本的情况下,让我们假设它作为主要功能执行,例如你说的话

python threading_example.py

在命令行上。 设置特殊变量后,它将执行import语句并加载这些模块。 然后它将评估def块,创建一个函数对象并创建一个名为myfunction的变量,该变量指向函数对象。 然后它将读取if语句并看到__name__等于"__main__" ,因此它将执行那里显示的块。

这样做的一个原因是有时你会编写一个模块( .py文件)来直接执行它。 或者,它也可以导入并在另一个模块中使用。 通过执行主检查,您可以仅在希望将模块作为程序运行时执行该代码,而在有人只想导入模块并自行调用函数时不执行该代码。

有关其他详细信息,请参阅此页面

注意 (由Stainsor提供):如果将代码放在函数定义之前,它将在main之前执行。

print("This code executes before main.") 

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

def functionB():
    print("Function B")

if __name__ == '__main__':
    functionA()
    functionB()

如果此模块确实是主模块,则此代码会导致:

This code executes before main. 
Function A 
Function B

如果这个模块不是主要的,你得到:

This code executes before main. 
__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))



__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__']设置为模块的名称。

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

如您所见,在执行文件时,Python将此文件中的globals()['__name__']"__main__"




if __name__ == "__main__"是使用python myscript.py类的命令从命令行运行脚本时运行的部分。




这里有很多不同的关于代码的机制,“如何”,但对我来说,除非我理解“为什么”,否则它们都没有意义。 这应该对新程序员特别有用。

取文件“ab.py”:

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

第二个文件“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.pyimport ab 。 import语句在导入时立即运行模块,因此ab的操作在xy的剩余部分之前执行。 完成ab ,继续使用xy

解释器使用__name__跟踪正在运行的脚本。 当您运行脚本时 - 无论您将其命名为什么 - 解释器将其称为"__main__" ,使其成为运行外部脚本后返回的主或“主”脚本。

从此"__main__"脚本调用的任何其他脚本都将其文件名指定为其__name__ (例如, __name__ == "ab.py" )。 因此, if __name__ == "__main__":是解释器的测试,用于确定它是否正在解释/解析最初执行的“home”脚本,或者它是否暂时窥视另一个(外部)脚本。 这为程序员提供了灵活性,使脚本的行为不同,如果它直接执行而不是外部调用。

让我们逐步完成上面的代码来了解发生了什么,首先关注的是未缩进的行以及它们在脚本中出现的顺序。 请记住,函数 - 或def - 块在它们被调用之前不会自行执行任何操作。 如果嘟to自己,翻译可能会说些什么:

  • 打开xy.py作为“主页”文件; 在__name__变量中将其__name__"__main__"
  • 使用__name__ == "ab.py"导入并打开文件。
  • 哦,一个功能。 我会记得的。
  • 好的,功能a() ; 我刚学会了这个。 打印' ab文件中函数 '。
  • 文件结束; 回到"__main__"
  • 哦,一个功能。 我会记得的。
  • 另一个。
  • 函数x() ; 好的,打印' 外围任务:可能在其他项目中很有用 '。
  • 这是什么? 一个if语句。 好吧,条件已经满足(变量__name__已设置为"__main__" ),所以我将进入main()函数并打印' main函数:这就是动作的位置 '。

底部两行表示:“如果这是"__main__"或”home“脚本,则执行名为main()的函数”。 这就是为什么你会看到一个def main(): block up top,它包含了脚本功能的主要流程。

为什么实现这个?

还记得我之前说的关于import语句的内容吗? 导入模块时,它不仅“识别”它并等待进一步的指令 - 它实际上运行脚本中包含的所有可执行操作。 因此,将脚本的内容放入main()函数中会有效隔离它,将其置于隔离状态,以便在由另一个脚本导入时不会立即运行。

同样,会有例外,但通常的做法是main()通常不会被外部调用。 所以你可能想知道另外一件事:如果我们不调用main() ,我们为什么要调用脚本呢? 这是因为许多人使用独立函数构建脚本,这些函数构建为独立于文件中的其余代码运行。 然后它们被称为脚本体内的其他地方。 这让我想到了这个:

但代码在没有它的情况下工作

恩,那就对了。 可以从不包含在main()函数中的内联脚本调用这些单独的函数。 如果你已经习惯了(就像我在编程的早期学习阶段一样)构建完全符合你需要的内联脚本,如果你再次需要这个操作,你会尝试再次弄清楚它。好吧,你不习惯你的代码的这种内部结构,因为它构建起来更复杂,而且阅读不那么直观。

但这是一个可能无法在外部调用其函数的脚本,因为如果这样做,它会立即开始计算和分配变量。 如果你正在尝试重新使用某个函数,那么你的新脚本可能与旧版本密切相关,而且会有相互矛盾的变量。

在拆分独立函数时,您可以通过将它们调用到另一个脚本中来重用以前的工作。 例如,“example.py”可能导入“xy.py”并调用x() ,使用“xy.py”中的“x”函数。 (也许它正在大写给定文本字符串的第三个单词;从数字列表中创建NumPy数组并对它们进行平方;或者去除3D表面的去除。可能性是无限的。)

(顺便说一句, 这个问题包含@kindall的答案,最终帮助我理解 - 为什么,而不是如何。不幸的是,它被标记为这个的副本,我认为这是一个错误。)




让我们以更抽象的方式看待答案:

假设我们在x.py中有这个代码:

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

当我们运行“x.py”时,块A和B运行。

但是当我们运行另一个模块时,只运行块A(而不是B),例如“y.py”,其中导入了xy并且从那里运行代码(就像“x.py”中的函数是从y.py调用。




以交互方式运行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__是什么以及它的作用非常重要。

什么是__name__

__name__DunderAlias - 可以被认为是一个全局变量(可以从模块访问),并以类似于global

它是一个字符串(全局如上所述),由type(__name__) (产生<class 'str'> type(__name__) <class 'str'> ),并且是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脚本运行,将返回文件的名称它起源于哪里。

实践:

作为变量意味着它的值可以被覆盖(“可以”并不意味着“应该”),覆盖__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__'

现在我们知道__name__的行为变得更加清晰:

if是一个流控制语句,如果给定的值为true,则包含将执行的代码块。 我们已经看到__name__可以使用__main__或从中导入的文件名。

这意味着如果__name__等于__main__那么该文件必须是主文件,并且必须实际运行(或者它是解释器),而不是导入到脚本中的模块或包。

如果确实__name__确实取了__main__的值,那么该代码块中的任何内容都将执行。

这告诉我们如果运行的文件是主文件(或者您直接从解释器运行),那么必须执行该条件。 如果它是一个包,那么它不应该,并且该值不会是__main__

模块:

__name__也可以在模块中用于定义模块的名称

变种:

使用__name__也可以做其他不太常见但有用的事情,我将在这里展示一些:

仅在文件是模块或包时执行:

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

如果文件是主文件,则运行一个条件,如果不是,则运行另一个条件:

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

您还可以使用它在包和模块上提供可运行的帮助功能/实用程序,而无需精心使用库。

它还允许模块作为主脚本从命令行运行,这也非常有用。




我认为最好用深入简单的方式打破答案:

__name__ :Python中的每个模块都有一个名为__name__的特殊属性。 它是一个内置变量,它返回模块的名称。

__main__ :与其他编程语言一样,Python也有一个执行入口点,即main。 '__main__' 是顶级代码执行的范围的名称 。 基本上,您有两种使用Python模块的方法:直接将其作为脚本运行,或者导入它。 当模块作为脚本运行时,其__name__设置为__main__

因此,当模块作为主程序运行时, __name__属性的值设置为__main__ 。 否则, __name__的值将设置为包含模块的名称。




if __name__ == "__main__":基本上是顶级脚本环境,它指定解释器('我具有最高优先级首先执行')。

'__main__'是顶级代码执行的范围的名称。 从标准输入,脚本或交互式提示中读取时,模块的__name__设置为'__main__'

if __name__ == "__main__":
    # Execute only if run as a script
    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.htmlhttps://docs.python.org/3.5/tutorial/modules.html




在本页的答案中,我一直在阅读这么多内容。 我会说,如果你知道这件事,肯定会理解那些答案,否则,你仍然感到困惑。

简而言之,您需要了解以下几点:

  1. import a动作实际运行所有可以在“a”中运行import a动作

  2. 由于第1点,您可能不希望在导入时在“a”中运行所有内容

  3. 要解决第2点中的问题,python允许您进行条件检查

  4. __name__是所有.py模块中的隐式变量; 导入__name__ ,a.py模块的__name__值设置为文件名“a”; 当a.py直接使用“python a.py”运行时,这意味着a.py是入口点,那么a.py模块的__name__值设置为字符串__main__

  5. 基于python如何为每个模块设置变量__name__的机制,你知道如何实现第3点吗? 答案很简单,对吧? 设置if条件: if __name__ == "__main__": ... ; 您甚至可以根据您的功能需要放置__name__ == "a"

python特别重要的是第4点! 其余的只是基本逻辑。




创建一个文件, a.py

print(__name__) # It will print out __main__

只要该文件直接运行显示这是主文件, __name__总是等于__main__

在同一目录中创建另一个文件b.py

import a  # Prints a

运行。它将打印一个,即导入的文件的名称。

因此,为了显示同一文件的两种不同行为,这是一个常用的技巧:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly



这个答案适用于学习Python的Java程序员。每个Java文件通常都包含一个公共类。您可以通过两种方式使用该类:

  1. 从其他文件中调用该类。你只需要在调用程序中导入它。

  2. 出于测试目的,单独运行类。

对于后一种情况,该类应包含一个public static void main()方法。在Python中,此目的由全局定义的标签提供'__main__'




最近,我在创建python(深度学习)课程时遇到了这个问题,并且根据我的理解并同意上面列出的顶级解释,我将详细说明

__name__=="__main__"

有时我们在.py文件中构造一个类,并在该类中定义了许多函数。但是我们不想为了一个目的而处理所有这些类函数。例如,用于创建类并定义一些用于数据创建的函数(.npy文件),而一些用于数据加载。所以,如果我们定义

__name__=="__main__"

XXX = CLASS_NAME()

xxx.create_data()

意味着如果我们调用.py文件,那么它只会创建数据而不会处理其他类函数。其他类函数(数据加载)也可以由其他类导入。




Related