Python中的"if __name__ == '__main__'"结构

10

我已经阅读了很多关于这个问题的文章:

if __name__ == '__main__'

但我不太理解... 我将向你分享代码,有没有更简洁的解释?

我创建了一个名为“ab.py”的文件:

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

a()

第二个文件是 "xy.py"

import ab

def b():
    print('b function')

def x():
    print ('s');

x()

if __name__ == "__main__" :
    b()
当我执行这段代码时,会得到以下输出:
A function in ab file
s
b function

这是什么意思?这个代码实际上在做什么?为什么我们要实现它?我们的代码没有它也可以工作。

if __name__ == "__main__":
    b()

1
我从这里得到了它 :( 我已经阅读过这个。 - Jaskaran Zap
这就像Java或C#中的 main(String [] args) 一样。 - Radinator
规范问题是 *if name == "main": 做什么?*(56个答案,7,000个赞。6年前)。 - Peter Mortensen
就像其他许多评论中所说的那样,这显然是一个重复的问题。 - Karl Knechtel
4个回答

38

你应该养成几乎总是使用这个的习惯。

if __name__ == '__main__': 后面的任何内容都只会在你显式运行文件时才会被执行。

python myfile.py

然而,如果你在其他地方导入 myfile.py

import myfile

if __name__ == '__main__': 下面的代码将不会被调用。


1
太棒了,解释得非常好! - rtrojanowski
1
非常好的解释。@Adam - selvakumar
1
这是一个如此简单而优雅的解释!!我在阅读了数页内容后,比之前更加困惑。这真的很有帮助! - Leo Optimo II
1
简单、简明扼要且准确的解释,正是我所寻找的。谢谢Adam。 - Tommy Gibbons

29

理解这个语句的一个非常简单的例子如下:

假设我们有以下名为using_name.py的Python脚本:


# Filename: using_name.py

if __name__ == '__main__':
    print 'This program is being run by itself'
else:
    print 'I am being imported from another module'

现在,请尝试做以下两件事并查看结果:


1)直接运行脚本

python using_name.py

结果

This program is being run by itself

2) 导入脚本

python

import using_name

结果

I am being imported from another module

1
这绝对是对这个问题最好的回答。 - Wayne Smallman

4
这段代码实际上在做什么?
当你执行 xy.py 时,你导入了 ab。导入语句在导入时运行模块,因此在 xy 的其余部分之前执行了 ab 的操作。完成 ab 后,它继续执行 xy。
解释器使用 __name__ 跟踪正在运行的脚本。无论你给脚本命名为什么,当你运行一个脚本时,解释器都会将其称为 "__main__"。这就是它跟踪哪个脚本是主文件的方式,也就是在调用另一个脚本后返回的脚本(你可能会说是“主页”脚本)。
从这个“主”脚本调用的任何其他脚本都被分配为其文件名作为其 __name__。因此,if __name__ == "__main__" : 这一行是解释器测试以确定它是否在运行它正在查看(解析)的脚本,还是暂时窥视另一个脚本。这使得程序员可以灵活地让脚本在外部调用时表现出不同的行为。
为了理解发生了什么,请首先关注未缩进的行以及它们在脚本中出现的顺序。请记住,函数或def块本身不会执行任何操作,直到它们被调用。如果解释器自言自语,可能会想到什么:
  • 打开xy.py
  • 使用__name__ab.py导入并打开文件。
  • 哦,一个函数。我会记住的。
  • 好的,函数a(); 我刚学会了。我猜我现在要打印了。
  • 文件结束; 回到'__main__'
  • 哦,一个函数。我会记住的。
  • 又一个。
  • 函数x(); 好的,打印's'。
  • 这是什么?一个if语句。嗯,条件已经满足(变量__name__已设置为'__main__'),所以我将打印'b function'。

然而,我认为您没有正确使用它。可能有例外情况,但底部两行应该是:

if __name__ == "__main__":
    main()

...这意味着“如果这是‘main’或主脚本,则执行名为main()的函数。这就是为什么你会看到一个def main():块在顶部,其中包含脚本功能的主要流程。

我们为什么要实现这个?

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

再次强调,会有例外情况,但通常做法是main()通常不会被外部调用。所以你可能会想到另一个问题:如果我们不调用main(),那么我们为什么还要调用脚本呢?这是因为许多人使用独立运行的函数来构建自己的脚本。然后在脚本的其他位置调用它们。这就带我来到了这个问题:

我们的代码即使没有它也可以工作

是的,你说得对。这些单独的函数可以从不包含在main()函数内部的内联脚本中调用。如果你习惯于(就像我在编程的早期学习阶段一样)构建内联脚本,以便精确地完成所需的任务,并且如果你需要再次执行该操作,你会尝试再次弄清楚它 - 那么,你可能不习惯代码的这种内部结构,因为它更复杂,阅读起来也不太直观。

但是,这可能是一个脚本,不能从外部调用其函数,因为如果这样做,它将开始计算和分配变量。而且,如果你试图重用一个函数,你的新脚本很可能与旧脚本密切相关,可能存在冲突的变量。

我应该顺便说一下,这个问题包含了kindall的一个答案,最终帮助我理解了-为什么,而不是如何。不幸的是,它被标记为这个问题的重复,我认为这是一个错误。(我是这个网站的新手,所以还不能标记它;如果你同意我的观点,请标记它以引起更多管理员的注意。)


这似乎不是有效的Python代码(缩进)-(?) - Peter Mortensen
好的,OP似乎已经离开了 ("上次出现超过1年前")。 - Peter Mortensen

0
简单来说,if __name__ == "__main__": 内的所有内容只有在Python解释器直接执行模块(例如 python module.py或者在导入后显式调用函数时才会运行。

示例:

文件 testFile.py

# This will always be executed even if this module is simply imported by other file or this module is the entry point
print "I will always run in any situation. Even when this module is 'just' imported"

if __name__ == "__main__":
    # This will be executed only when this module is the entry point eg. python testFile.py but not if this file is imported
    print "I will only run if this module (testFile.py) is executed directly by the Python interpreter"

文件 app.py

import testFile

运行它

python testFile.py

输出

I will always run in any situation. Even when this module is 'just' imported.

I will only run if this module (file *testFile.py*) is executed directly by the Python interpreter.

运行它

python app.py

输出

I will always run in any situation. Even when this module is 'just' imported

如果你想了解 __name__ 变量的内部机制: 请查看 if __name__ == "__main__": 做什么?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接