繁体   English   中英

if __name__ == "__main__": 做什么?

What does if __name__ == "__main__": do?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

这是做什么的,为什么要包含if语句?

if __name__ == "__main__":
    print("Hello, World!")

这个问题解释了代码的作用以及它是如何工作的。 如果您试图关闭某人应该使用此成语而不是使用此成语的问题,请考虑将其关闭为为什么在我导入它时 Python 正在运行我的模块,以及如何停止它? 反而。

42 个回复

简答

它是样板代码,可防止用户在无意中意外调用脚本。 以下是脚本中省略守卫时的一些常见问题:

  • 如果您在另一个脚本中导入无保护脚本(例如import my_script_without_a_name_eq_main_guard ),则后一个脚本将触发前者在导入时运行并使用第二个脚本的命令行参数 这几乎总是一个错误。

  • 如果您在无保护脚本中有一个自定义类并将其保存到一个 pickle 文件中,那么在另一个脚本中将其取消腌制将触发无保护脚本的导入,与上一个项目符号中概述的问题相同。

长答案

为了更好地理解这为什么以及如何重要,我们需要退后一步来了解 Python 如何初始化脚本以及它如何与其模块导入机制进行交互。

每当 Python 解释器读取源文件时,它会做两件事:

  • 它设置了一些特殊变量,例如__name__ ,然后

  • 它执行在文件中找到的所有代码。

让我们看看它是如何工作的,以及它与您对我们在 Python 脚本中经常看到的__name__检查的问题有何关系。

代码示例

让我们使用一个稍微不同的代码示例来探索导入和脚本是如何工作的。 假设以下内容位于名为foo.py的文件中。

# Suppose this is foo.py.

print("before import")
import math

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

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

print("before __name__ guard")
if __name__ == '__main__':
    function_a()
    function_b()
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"分配给__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. 它在"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 function_a"

  2. 它执行def块,创建一个函数对象,然后将该函数对象分配给一个名为function_a的变量。

  3. 它打印字符串"before function_b"

  4. 它执行第二个def块,创建另一个函数对象,然后将其分配给一个名为function_b的变量。

  5. 它打印字符串"before __name__ guard"

仅当您的模块是主程序时

  1. 如果您的模块是主程序,那么它将看到__name__确实设置为"__main__"并调用这两个函数,打印字符串"Function A""Function B 10.0"

仅当您的模块被另一个模块导入时

  1. 相反)如果您的模块不是主程序而是由另一个程序导入,那么__name__将是"foo" ,而不是"__main__" ,它会跳过if语句的主体。

总是

  1. 在这两种情况下,它都会打印字符串"after __name__ guard"

概括

总而言之,以下是两种情况下打印的内容:

# What gets printed if foo is the main program
before import
before function_a
before function_b
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 function_a
before function_b
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 function_a():
    print("a1")
    from foo2 import function_b
    print("a2")
    function_b()
    print("a3")

def function_b():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    function_a()
    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 function_a():
    print("a1")
    from foo3 import function_b
    print("a2")
    function_b()
    print("a3")

def function_b():
    print("b")

print("t1")
print("m1")
function_a()
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")

当您的脚本通过将其作为命令传递给 Python 解释器来运行时,

python myscript.py

所有处于缩进级别 0 的代码都会被执行。 定义的函数和类已经定义好了,但是它们的代码都没有运行。 与其他语言不同,没有自动运行的 main( main()函数 - main()函数隐含地是顶层的所有代码。

在这种情况下,顶层代码是一个if块。 __name__是一个内置变量,计算结果为当前模块的名称。 但是,如果直接运行模块(如上面的myscript.py中),则__name__改为设置为字符串"__main__" 因此,您可以通过测试来测试您的脚本是直接运行还是被其他东西导入

if __name__ == "__main__":
    ...

如果你的脚本被导入另一个模块,它的各种函数和类定义将被导入,它的顶级代码将被执行,但上面if子句的 then-body 中的代码不会作为条件运行不满足。 作为一个基本示例,请考虑以下两个脚本:

# 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__"

创建以下两个文件:

# a.py

import b
# b.py

print("__name__ equals " + __name__)

if __name__ == '__main__':
    print("if-statement was executed")

现在单独运行每个文件。


运行python a.py

$ python a.py
__name__ equals b

a.py被执行时,它会导入模块b 这会导致b中的所有代码运行。 Python 将b模块中的globals()['__name__']设置为模块的名称b


运行python b.py

$ python b.py
__name__ equals __main__
if-statement was executed

当只执行文件b.py时,Python 将此文件中globals()['__name__']设置为"__main__" 因此,这次if语句的计算结果为True

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

有了上述内容,您的代码只会在您将其作为主要模块运行(或有意从另一个脚本中调用它)时执行。

更好的方法

不过,有一种 Pythonic 方法可以改进这一点。

如果我们想从模块外部运行这个业务流程怎么办?

如果我们将开发和测试的代码放入这样的函数中,然后立即检查'__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()

if __name__ == "__main__"是当脚本从(比如说)命令行使用类似python myscript.py的命令运行时运行的部分。

if __name__ == "__main__":做什么?

__name__是一个存在于所有命名空间中的全局变量(在 Python 中,全局实际上是指模块级别)。 它通常是模块的名称(作为str类型)。

然而,作为唯一的特殊情况,在你运行的任何 Python 进程中,如在 mycode.py 中:

python mycode.py

否则匿名的全局命名空间被分配了'__main__'的值给它的__name__

因此,包括最后几行

if __name__ == '__main__':
    main()
  • 在 mycode.py 脚本的末尾,
  • 当它是由 Python 进程运行的主要入口点模块时,

将导致您的脚本唯一定义的main函数运行。

使用此构造的另一个好处:您还可以将代码作为模块导入另一个脚本中,然后在您的程序决定时运行 main 函数:

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

这里对所讨论的代码机制有很多不同的看法,即“如何”,但对我来说,在我理解“为什么”之前,这一切都没有意义。 这应该对新程序员特别有帮助。

获取文件“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.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__"
  • 哦,一个函数。 我会记住的。
  • 另一个。
  • 函数x() ; 好的,打印“外围任务:可能在其他项目中有用”。
  • 这是什么? 一个if语句。 嗯,条件已经满足(变量__name__已设置为"__main__" ),所以我将进入main()函数并打印 ' main function: this is where the action is '.

下面两行的意思是:“如果这是"__main__"或“home”脚本,请执行名为main()的函数”。 这就是为什么您会在顶部看到一个def main():块,其中包含脚本功能的主要流程。

为什么要实施这个?

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

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

但是代码没有它就可以工作

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

但这是一个可能无法在外部调用其函数的脚本,因为如果这样做,它将立即开始计算和分配变量。 如果您尝试重用一个函数,那么您的新脚本与旧脚本的相关性非常密切,可能会出现变量冲突。

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

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

if __name__ == '__main__':下的代码只有在模块作为脚本调用时才会执行。

例如,考虑以下模块my_test_module.py

# my_test_module.py

print('This is going to be printed out, no matter what')

if __name__ == '__main__':
    print('This is going to be printed out, only if user invokes the module as a script')

第一种可能性:在另一个模块中导入my_test_module.py

# main.py

import my_test_module

if __name__ == '__main__':
    print('Hello from main.py')

现在,如果您调用main.py

python main.py

>> 'This is going to be printed out, no matter what'
>> 'Hello from main.py'

请注意,仅执行my_test_module中的顶级print()语句。


第二种可能性:调用my_test_module.py作为脚本

现在,如果您将my_test_module.py作为 Python 脚本运行,两个print()语句都将被执行:

python my_test_module.py

>>> 'This is going to be printed out, no matter what'
>>> 'This is going to be printed out, only if user invokes the module as a script'

如需更全面的说明,您可以阅读What does if __name__ == '__main__' do in Python

当我们的模块( M.py )中有某些语句时,我们希望在它作为 main (未导入)运行时执行,我们可以将这些语句(测试用例,打印语句)放在这个if块下。

默认情况下(当模块作为主模块运行时,未导入) __name__变量设置为"__main__" ,当它被导入时__name__变量将获得不同的值,很可能是模块的名称( 'M' )。 这有助于一起运行模块的不同变体,并分离它们的特定输入和输出语句以及是否有任何测试用例。

简而言之,使用这个 ' if __name__ == "main" ' 块来防止在导入模块时运行(某些)代码。

简而言之, __name__是为每个脚本定义的变量,用于定义脚本是作为主模块运行还是作为导入模块运行。

所以如果我们有两个脚本;

#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++ 中的结构问题,如果文件没有实现“main”函数,那么它就无法编译为可执行文件,如果确实如此,然后它不能用作库。

假设您编写了一个很棒的 Python 脚本,并且您实现了一大堆可用于其他目的的函数。 如果我想使用它们,我可以只导入您的脚本并使用它们而不执行您的程序(假设您的代码仅在if __name__ == "__main__":上下文中执行)。 而在 C/C++ 中,您必须将这些部分分成一个单独的模块,然后包含该文件。 想象下面的情况;

C中复杂的导入

箭头是导入链接。 对于三个模块,每个模块都试图包含以前的模块代码,有六个文件(九个,计算实现文件)和五个链接。 这使得很难将其他代码包含到 C 项目中,除非将其专门编译为库。 现在为 Python 描绘它:

Python 中的优雅导入

您编写一个模块,如果有人想使用您的代码,他们只需导入它, __name__变量可以帮助将程序的可执行部分与库部分分开。

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

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

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

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

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

简而言之,你需要知道几点:

  1. import a action 实际上运行所有可以在a.py中运行的东西,这意味着a.py中的每一行

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

  3. 为了解决第 2 点中的问题,Python 允许您使用条件检查

  4. __name__是所有.py模块中的隐式变量:

  • a.pyimport ed 时, a.py模块的__name__的值被设置为其文件名“ a
  • 当使用“ python a.py ”直接运行a.py时,__ __name__的值设置为字符串__main__
  1. 基于Python如何为每个模块设置变量__name__的机制,你知道如何实现第3点吗? 答案很简单,对吧? 使用if条件: if __name__ == "__main__": // do A
  • 然后python a.py将运行该部分// do A
  • import a将跳过部分// do A
  1. 您甚至可以根据您的功能需要放置 if __name__ == "a" ,但很少这样做

Python 的特别之处在于第 4 点! 其余的只是基本逻辑。

我一直在阅读此页面上的所有答案。 我想说,如果你知道这件事,你肯定会明白那些答案,否则,你还是一头雾水。

当您以交互方式运行 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__":
    main()

它检查 Python 脚本的__name__属性是否为"__main__" 换句话说,如果程序本身被执行,属性将为__main__ ,因此程序将被执行(在本例中为main()函数)。

但是,如果您的 Python 脚本被模块使用,则if语句之外的任何代码都将被执行,因此if __name__ == "__main__"仅用于检查程序是否用作模块,因此决定是否运行代码。

在解释有关if __name__ == '__main__'任何内容之前,了解__name__是什么以及它的作用很重要。

什么是__name__

__name__是一个DunderAlias - 可以被认为是一个全局变量(可从模块访问)并且以类似于global的方式工作。

它是由type(__name__)指示的字符串(如上所述的全局)(产生<class 'str'> ),并且是Python 3Python 2版本的内置标准。

在哪里

它不仅可以在脚本中使用,还可以在解释器和模块/包中找到。

口译员:

>>> print(__name__)
__main__
>>>

脚本:

测试文件.py

print(__name__)

导致__main__

模块或包:

一些文件.py:

def somefunction():
    print(__name__)

测试文件.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__'

现在我们知道了__name__的行为,事情变得更清楚了:

if是一个包含代码块的流控制语句,如果给定的值为真,则将执行该语句。 我们已经看到__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

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

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

当从命令行调用 Python 文件时,它是特殊的。 这通常用于调用“main()”函数或执行其他适当的启动代码,例如命令行参数处理。

它可以写成几种方式。 另一个是:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

我并不是说你应该在生产代码中使用它,但它可以说明if __name__ == '__main__'没有什么“神奇”。

它只是在 Python 文件中调用 main 函数的约定。

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

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

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

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

系统(Python 解释器)为源文件(模块)提供了许多变量。 您可以随时获取它们的值,因此,让我们关注__name__变量/属性:

当 Python 加载源代码文件时,它会执行其中找到的所有代码。 (请注意,它不会调用文件中定义的所有方法和函数,但会定义它们。)

不过,在解释器执行源代码文件之前,它会为该文件定义一些特殊变量; __name__是 Python 为每个源代码文件自动定义的特殊变量之一。

如果 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 ”。

希望这会有所帮助。

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

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

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

考虑:

print __name__

上面的输出是__main__

if __name__ == "__main__":
  print "direct method"

上述陈述为真,并打印出“直接方法” 假设如果他们在另一个类中导入这个类,它不会打印“直接方法” ,因为在导入时,它将设置__name__ equal to "first model name"

您可以使该文件可用作脚本以及可导入模块

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

的原因

if __name__ == "__main__":
    main()

主要是为了避免直接导入代码会引起的导入锁定问题。 如果您的文件被直接调用(即__name__ == "__main__"情况),您希望main()运行,但如果您的代码已导入,则导入器必须从真正的主模块输入您的代码以避免导入锁定问题。

副作用是您自动登录到支持多个入口点的方法。 您可以使用main()作为入口点来运行您的程序,但您不必. 虽然setup.py需要main() ,但其他工具使用备用入口点。 例如,要将文件作为gunicorn进程运行,您需要定义一个app()函数而不是main() setup.py一样, gunicorn导入您的代码,因此您不希望它在导入时做任何事情(因为导入锁定问题)。

Python 中的每个模块都有一个名为__name__的属性。 直接运行模块时__name__属性的值为__main__ ,如python my_module.py 否则(就像你说import my_module时一样) __name__的值是模块的名称。

简短的小例子来解释。

脚本test.py

apple = 42

def hello_world():
    print("I am inside hello_world")

if __name__ == "__main__":
    print("Value of __name__ is: ", __name__)
    print("Going to call hello_world")
    hello_world()

我们可以直接执行

python test.py

输出

Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world

现在假设我们从另一个脚本调用上述脚本:

脚本external_calling.py

import test

print(test.apple)
test.hello_world()

print(test.__name__)

当您执行此操作时,

python external_calling.py

输出

42
I am inside hello_world
test

因此,上面的内容是不言自明的,当您从另一个脚本调用test时, test.py中的 if loop __name__将不会执行。

如果您是初学者,那么您现在唯一需要的答案可能是该代码对于简单的脚本来说是不必要的。 仅当您希望能够import脚本(或unpickle等;请参阅此处的其他答案以了解其他一些非初学者场景)时,它才有用。

换句话说, if __name__守卫是一种将代码隐藏在其他代码之外的机制。 如果您没有特定的理由隐藏某些内容,请不要:如果您不需要从import中隐藏某些代码,请不要将其置于此保护之下,如果需要,请尽可能少地隐藏。

稍微详细一点,假设您有一个简单的脚本fib.py (改编自这个答案):

# XXX FIXME: useless (see below)
if __name__ == "__main__":
    n = int(input('Write a number: '))
    a, b = 0, 1
    while b < n:
        a, b = b, a+b
    print('Fibonacci number %i: %i' % (n, b))

现在,如果你只是运行python fib.py它工作正常。 但是__name__在这种情况下将始终是"__main__" ,因此该条件实际上是不必要的。 脚本可以简化为

n = int(input('Write a number: '))
a, b = 0, 1
while b < n:
    a, b = b, a+b
print('Fibonacci number %i: %i' % (n, b))

现在,您无法使用新版本import fib ,但如果您一开始不打算这样做,那么这个版本实际上更好,因为它更简单、更清晰。

如果您确实希望能够import fib ,那么第一个版本也是无用的,因为有用的代码位于import此文件时不会运行的部分中(在这种情况下__name__不会是"__main__" )。 在这种情况下,正确的设计是重构代码,以便有用的部分位于一个函数中,您可以在import后运行它。

def main():
    n = int(input('Write a number: '))
    a, b = 0, 1
    while b < n:
        a, b = b, a+b
    print('Fibonacci number %i: %i' % (n, b))

if __name__ == "__main__":
    main()

现在,如果您import fib ,则不会执行对main()的调用; 但是当你运行python fib.py时,它会。

实际上,更好的设计仍然是将可重用部分(实际计算)与用户可见的输入/输出隔离开来:

def fibn(n: int) -> int:
    a, b = 0, 1
    while b < n:
        a, b = b, a+b
    return b

def main() -> None:
    n = int(input('Write a number: '))
    print('Fibonacci number %i: %i' % (n, fibn(n)))

if __name__ == "__main__":
    main()

现在,您可以from fib import fibn并从执行此import的代码中调用fibn()函数。

(我调用函数fibn()只是为了更清楚地说明这个示例中的内容。在现实生活中,您可能会调用它fib()并执行from fib import fib 。)

同样,如果你想重用它,你可以import并调用main函数。

回到问题中的代码,我同样会将代码从if移动到一个函数中,以便调用者可以根据需要调用该函数。

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

if __name__ == "__main__":
    main()

这改变了lock变量的范围; 如果周围的代码需要访问它,则需要将其设为global (或者,也许更好,重构mainreturn lock ,并让调用者在自己的局部变量中捕获值)。

(与 C 等语言不同,名称main对 Python 没有特定含义;但将其用作将要运行的事物的名称是一种常见约定。您仍然必须实际显式调用它,例如main() ,与 C 不同。)

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

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

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

对于后一种情况,该类应包含一个公共静态 void main() 方法。 在 Python 中,这个目的是由全局定义的标签'__main__'实现的。

如果这个 .py 文件被其他 .py 文件导入,则if语句下的代码不会被执行。

如果这个 .py 在 shell 下由python this_py.py运行,或者在 Windows 中双击。 if语句下的代码将被执行。

它通常是为测试而编写的。

如果 Python 解释器正在运行特定模块,则__name__全局变量将具有值"__main__"

  def a():
      print("a")

  def b():
      print("b")

  if __name__ == "__main__":

          print ("you can see me")
          a()
  else:

          print ("You can't see me")
          b()

当你运行这个脚本时,它会打印你可以看到我

一个

如果你导入这个文件,说 A 到文件 B,然后执行文件 B,那么if __name__ == "__main__" in file A 变为 false,所以它打印You can't see me

b

简单来说:

您在if __name__ == "__main__":下看到的代码只会在您的 Python 文件作为python example1.py执行时被调用

但是,如果您希望将 Python 文件example1.py作为模块导入以使用另一个 Python 文件(例如example2.py ),则if __name__ == "__main__":下的代码将不会运行或生效。

我们经常看到__name__ == '__main__':

它检查是否正在导入模块。

也就是说, if块中的代码只有在代码直接运行时才会被执行。 这里directly表示not imported

让我们看看它使用打印模块名称的简单代码做了什么:

# 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__

Python 中的每个模块都有一个名为__name__的特殊属性。 当模块作为主程序执行时(例如,运行python foo.py ), __name__属性的值设置为'__main__'

否则, __name__的值将设置为调用它的模块的名称。

创建一个文件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 文件,a.py 和 b.py。 现在,a.py 导入 b.py。 我们运行 a.py 文件,其中首先执行“import b.py”代码。 在其余的 a.py 代码运行之前,文件 b.py 中的代码必须完全运行。

在 b.py 代码中,有一些代码是该文件 b.py 独有的,我们不希望导入 b.py 文件的任何其他文件(除了 b.py 文件)运行它。

这就是这行代码检查的内容。 如果它是运行代码的主文件(即 b.py),在这种情况下它不是(a.py 是运行的主文件),那么只有代码被执行。

当一个 python 文件被执行时,它会创建许多特殊变量,例如__name__变量__name__保存文件的名称。 你的问题的答案是

if __name__ == "__main__":
       #do something

这意味着如果正在执行的文件的名称作为源文件而不是模块运行,那么它将运行其中的代码,这可以通过一个简单的例子来证明。 创建两个 python 文件foo.pysecond.py然后在foo.py输入这个

if __name__ == "__main__":
       print("file is not imported")
else:
       print("file is imported")

second.py输入这个

import foo

if foo.__name__ == "__main__":
       print("file is not imported")
else:
       print("file is imported")

除此之外,如果你会这样做print(__name__)那么它会打印__main__为什么? 因为 file 作为主要源运行,如果你要执行print(foo.__name__)它将打印 foo 因为__name__变量的默认值是文件的名称,默认情况下我的意思是你也可以改变它来做这只需转到foo.py并执行此操作__name__ = "name"然后当您运行该文件时

__name__ = "hello world"
print(__name__)

然后输出将是

hello world

就像在C编程语言中的main功能一样,它只是运行文件的入口点。

PYTHON MAIN FUNCTION是任何程序的起点。 程序运行时,python解释器依次运行代码。 Main 函数仅在作为 Python 程序运行时才执行...

def main():
     print ("i am in the function")
print ("i am out of function")

当您运行脚本显示时:

i am out of function

而不是代码“我在函数中”这是因为我们没有声明调用函数“if__name__==” main “。如果你使用它:

def main():
     print ("i am in the function")


if __name__ == "__main__":
    main()

print ("i am out of function")

输出等于

i am in the function
i am out of function

在 Python 中,“if__name__==” main允许您将 Python 文件作为可重用模块或独立程序运行。

当 Python 解释器读取源文件时,它将执行其中找到的所有代码。 当 Python 将“源文件”作为主程序运行时,它会将特殊变量( name )设置为具有值(“ main ”)。

当您执行 main 函数时,它将读取“if”语句并检查name是否等于main

在 Python 中,“if__name__==” main允许您将 Python 文件作为可重用模块或独立程序运行。

只有你需要知道的事实

这个问题的其他答案太长了。 实际的机制非常简单,只有两个基本事实:

  1. 纯 Python 模块总是在创建时将变量__name__设置为字符串"__main__"

  2. 导入模块的副作用是将__name__变量更改为没有.py扩展名的基本文件名。

如何使用这些信息

人们写__name__ == '__main__'来测试一个模块是否已经被导入。

导入时通常会有一些不应运行的代码:测试代码、一次性使用代码、命令行前端或 Web 服务器前端。

这个想法是运行模块的人直接希望这些操作发生,但导入模块的人只想直接访问函数、类和变量。

从其他答案中可以看出,人们似乎可以无休止地谈论这个话题,但这确实是一件简单的事情,而且很容易掌握。 Python 教程在大约两分钟的阅读时间内涵盖了这一点 不要让其他答案因过度解释而淹没您:-)

if __name__ = "__main__"意味着如果你像python foo.py一样正常运行 python 文件,它会将特殊变量__name__分配给"__main__"但是如果你像 "import foo" 这样导入文件,它会将__name__分配给"foo"并且不会运行该函数。

当您执行模块(源文件)时,if-condition 检查模块是直接调用还是从另一个源文件调用。 这里直接表示不进口。

如果直接调用执行,模块名称设置为“main”,然后执行if块内的代码。

我是 Python 的初学者,但我想在这里写作。

假设我在维基百科上编写了用于网页抓取的函数和类 当然,这可能不是一个很好的例子 我想在另一个程序中使用这些函数而不重写它

好吧,我导入它们,但在该文件的末尾我放了 __ name __ = '__ main __'

当我们导入一个模块的时候,里面的所有代码都是从头到尾执行的,但是当达到条件的时候,就不会运行 func ,fucn2 and ...,这是维基百科的scrape

那么在全局范围内 Python __ name __ 被定义为当前程序的 '__ main __'

当我们导入一个模块时,它被定义为我们当前程序命名空间中的一个变量,当前程序 __ name __ is '__ main __'

#test.py
def func():
    #do somthing
    pass
def func2():
    #do somthing
    pass
print('The program name is set to',globals()['__name__'])

if __name__=='__main__':
    #in current program __name__ is equal '__main__' 
    func('https://www.wikipedia.org')
    func2('https://www.wikipedia.org')
    #or do more job
    
import test1
print('inside of current program')
print('name is current program',__name__)
print(globals()['test1'])
test1.func('another site')
test1.func2('another site')

输出

inside of test 1
name of program is set to  test1
end of madule
inside of current
__main__
<module 'test1' from 'C:\\users\\ir\\appdata\\local\\programs\\python\\python38\\lib\\test1.py'>

你可以用这个简单的例子检查特殊变量__name__

创建文件 1.py

if __name__ == "__main__":
    print("file1 is being run directly")
else:
    print("file1 is being imported")

创建 file2.py

import file1 as f1

print("__name__ from file1: {}".format(f1.__name__))
print("__name__ from file2: {}".format(__name__))

if __name__ == "__main__":
    print("file2 is being run directly")
else:
    print("file2 is being imported")

执行file2.py

输出

file1 is being imported
__name__ from file1: file1
__name__ from file2: __main__
file2 is being run directly

简单的答案是在if name == " main ":下编写的代码,如果您将其导入另一个文件,则不会执行。

4 如果 __name__ != __main__:

刚开始学Flask,对代码有点迷茫 文件名为 app.py。 当我在终端中使用命令python app.py时,结果是 但是当我在 PyCharm 中运行代码时,我得到的是: 如果我像这样修改代码: 结果是: 我在终端中这样做了,烧瓶无法启动,结果是: 那么,如何来_名_在终 ...

5 如果 __name__ == "__main__":

在 .py 文件中,我有一些函数在 if name == " main " 中被调用:除此之外,chrome 驱动程序也在那里初始化。 定义函数1:定义函数2: 现在,我想在另一个文件中调用整个文件/模块。 我该怎么办? 什么是最简单的方法? ...

6 如果__name__ ==“ __main__”

我正在处理两个python文件。 一旦完成,我计划从另一个呼叫另一个: 如果我调用main.py,我希望它也可以运行subfile.py 。 有时,我将单独运行subfile.py并希望它自己正常运行。 现在,在subfile.py ,应该将导入命令嵌套在if __name__ = ...

7 “/1/2/3/".split("/”)

它太热了我可能会被推迟。 什么是开头和结尾的空元素? 编辑:谢谢大家,我把它归结为热诱导的大脑失败。 从http://docs.python.org/library/stdtypes.html开始 ,文档并不是最清晰的 在第一个之前,或在最后一个“/”之后是否有一个单词? ...

10 Doctrine ORM\\Table(name="name") 不起作用

我的实体类: 但是当我添加一个客户时它会抛出这个错误,它正在寻找错误的表。 SQLSTATE[42S02]:未找到基表或视图:1146 表“database.customerentity”不存在 我确实尝试过,但没有帮助: 模式生成显示了这一点: 我究竟做错了什么? 我也清了 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM