如果 __name__ == "__main__":会做什么?

2024-11-15 08:36:00
admin
原创
24
摘要:问题描述:这有什么作用?为什么要包括这个if声明?if __name__ == "__main__": print("Hello, World!") 如果您试图关闭某人应该使用此习语但没有使用的问题,请考虑将其关闭为为什么 Python 在导入模块时运行它,以及...

问题描述:

这有什么作用?为什么要包括这个if声明?

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

如果您试图关闭某人应该使用此习语但没有使用的问题,请考虑将其关闭为为什么 Python 在导入模块时运行它,以及如何停止它?的副本。对于某人根本没有调用任何函数或错误地期望名为的函数main自动用作入口点的问题,请使用为什么在我启动 Python 脚本时 main() 函数不运行?脚本从哪里开始运行?。


解决方案 1:

简短答案

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

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

  • 如果您在无防护脚本中有一个自定义类并将其保存到 pickle 文件中,则在另一个脚本中对其进行取消防护将触发无防护脚本的导入,并会出现上一个项目中概述的相同问题。

长答案

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

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

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

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

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

代码示例

让我们使用略有不同的代码示例来探索导入和脚本的工作原理。假设以下内容位于名为的文件中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"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. 它打印字符串"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")

解决方案 2:

当你的脚本作为命令传递给 Python 解释器运行时,

python myscript.py

所有缩进级别为 0 的代码都会被执行。定义的函数和类确实被定义了,但它们的代码都不会运行。与其他语言不同,没有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__"

解决方案 3:

创建以下两个文件:

# 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 将模块globals()['__name__']中的设置b为模块名称b

跑步python b.py

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

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

解决方案 4:

这做什么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()

解决方案 5:

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

解决方案 6:

做什么if __name__ == "__main__":

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

但是,唯一的特殊情况是,无论您运行什么 Python 进程,如 mycode.py 中所示:

python mycode.py

'__main__'否则,匿名的全局命名空间将被赋予其的值__name__

因此,包括最后几行

if __name__ == '__main__':
    main()
  • 在 mycode.py 脚本的末尾,

  • 当它是 Python 进程运行的主要入口点模块时,

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

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

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

解决方案 7:

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

以文件“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 作为“home”文件;在变量"__main__"中调用它__name__

  • 使用 导入并打开文件__name__ == "ab.py"

  • 哦,一个功能。我会记住的。

  • 好的,函数a();我刚刚学到了。打印“ ab 文件中的函数”。

  • 文件结束;返回"__main__"

  • 哦,一个功能。我会记住的。

  • 再来一个。

  • 功能x();确定,打印‘外围任务:可能在其他项目中有用’。

  • 这是什么?一个if语句。好吧,条件已经满足(变量__name__已设置为"__main__"),所以我将进入main()函数并打印“主函数:这是操作所在的地方”。

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

为什么要实施这个?

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

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

但代码没有它也能工作

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

但这个脚本可能无法让其函数被外部​​调用,因为如果这样做,它会立即开始计算和分配变量。如果您尝试重新使用某个函数,则新脚本与旧脚本的关联性可能非常密切,以至于会出现冲突的变量。

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

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

解决方案 8:

当模块作为脚本调用时,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'

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


第二种可能性: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'

有关更全面的解释,您可以阅读Python 中的作用是什么if __name__ == '__main__'

解决方案 9:

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

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

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

解决方案 10:

简单地说,__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++ 中,如果文件未实现“主”函数,则无法将其编译为可执行文件,如果实现了,则无法将其用作库。

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

C 中的复杂导入

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

Python 中的优雅导入

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

解决方案 11:

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

假设我们有这样的代码x.py

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

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

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

解决方案 12:

简而言之,你需要了解几点:

  1. import a操作实际上运行了所有可以运行的操作a.py,也就是说a.py

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

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

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

  • a.py被执行时,模块import的值被设置为其文件名“ ”__name__`a.py`a

  • a.py直接使用“ ”运行时python a.py, 的值__name__被设置为字符串__main__

  1. 根据 Python 为每个模块设置变量的机制__name__,你知道如何实现第 3 点吗?答案很简单,对吧?使用if条件:if __name__ == "__main__": // do A

  • 然后python a.py将运行该部分// do A

  • 并将import a跳过该部分// do A

  1. __name__ == "a"你甚至可以根据你的功能需要放置它,但很少这样做

Python 最特别的地方就是第 4 点!其余的只是基本逻辑。

我已经阅读了本页上的大量答案。我想说,如果你知道这件事,你肯定会理解这些答案,否则,你仍然感到困惑。

解决方案 13:

当你以交互方式运行 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.

解决方案 14:

考虑:

if __name__ == "__main__":
    main()

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

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

解决方案 15:

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

什么是__name__

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

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

在哪里

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

翻译:

>>> print(__name__)
__main__
>>>

脚本:

测试文件.py

print(__name__)

导致__main__

模块或包:

某些文件.py:

def somefunction():
    print(__name__)

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

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

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

解决方案 16:

我认为最好用深入而简单的语言来解释答案:

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

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

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

解决方案 17:

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

它可以以多种方式编写。另一种是:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

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

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

解决方案 18:

如果你是初学者,那么你现在唯一需要的答案可能是,这段代码对于简单的脚本来说是不必要的。只有当你想在你的脚本中使用它时它才有用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调用该函数。fibn()`import`

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

请注意更加模块化和可重复使用的设计;该fibn函数包含实际计算,但没有用户界面部分;并且令人讨厌的交互式 I/O 被分离到main函数中,以便您可以绕过它(或者当然,如果您愿意,可以调用它)。

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


(问题中的代码随后被简化为只是print("Hello, World!")但我将其留在这里,因为它可能对更真实的场景具有指导意义。)

回到问题中的代码,我同样会将代码从移到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,并让调用者在其自己的局部变量中捕获该值)。

解决方案 19:

系统(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 ”。

希望这会有所帮助。

解决方案 20:

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

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

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

解决方案 21:

考虑:

print __name__

上面的输出是__main__

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

上述语句是正确的,并打印“直接方法”。假设他们在另一个类中导入了此类,则不会打印“直接方法”,因为在导入时,它将设置__name__ equal to "first model name"

解决方案 22:

简单来说:

下面的代码if __name__ == "__main__":只有在 Python 文件执行时才会被调用python example1.py

然而,如果您希望将您的 Python 文件example1.py作为模块导入以便与另一个 Python 文件一起使用,那么example2.py下面的代码if __name__ == "__main__":将不会运行或产生任何效果。

解决方案 23:

您可以使该文件既可用作脚本,也可用作可导入模块

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

解决方案 24:

原因是

if __name__ == "__main__":
    main()

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

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

解决方案 25:

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

因此,上述内容是不言而喻的,当您从另一个脚本调用测试__name__时,if loop intest.py将不会执行。

解决方案 26:

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

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

  2. 单独运行该类,以进行测试目的。

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

解决方案 27:

我们if __name__ == '__main__':经常见到。

它检查模块是否被导入。

也就是说,if只有代码直接运行时,块内的代码才会被执行。这里的“直接”是指“不被导入”。

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

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

解决方案 28:

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

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

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

解决方案 29:

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

运行此脚本时,它会打印:

you can see me
a

如果你导入此文件,说A文件B,并执行文件,Bif __name__ == "__main__"文件中的内容A变为False,因此它会打印:

You can't see me
b

解决方案 30:

所有答案几乎都解释了该功能。但我将提供一个使用示例,这可能有助于进一步澄清这一概念。

假设有两个 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主文件正在运行),则只执行代码。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用