什么是 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__, , 进而

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

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

代码示例

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

# Suppose this is foo.py.

print("before import")
import math

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

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

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
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, ,剥去 .py, ,并将该字符串分配给您的模块 __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 functionA".

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

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

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

  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 functionA
before functionB
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 functionA
before functionB
before __name__ guard
after __name__ guard

为什么会这样?

您可能自然想知道为什么有人想要这个。好吧,有时你想写一个 .py 文件既可以被其他程序和/或模块用作模块,也可以作为主程序本身运行。例子:

  • 您的模块是一个库,但您希望有一个脚本模式,可以运行一些单元测试或演示。

  • 您的模块仅用作主程序,但它有一些单元测试,测试框架通过导入来工作 .py 文件,例如您的脚本和运行特殊测试功能。您不希望它仅仅因为正在导入模块而尝试运行脚本。

  • 您的模块主要用作主程序,但它也为高级用户提供了程序员友好的 API。

除了这些示例之外,在 Python 中运行脚本只需设置一些神奇的变量并导入脚本,这很优雅。“运行”脚本是导入脚本模块的副作用。

深思熟虑

  • 问题:我可以有多个吗 __name__ 检查块?回答:这样做很奇怪,但语言不会阻止你。

  • 假设以下内容在 foo2.py. 。如果你说会发生什么 python foo2.py 在命令行上?为什么?

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • 现在,弄清楚如果删除会发生什么 __name__ 报到 foo3.py:
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
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()函数隐含了顶层的所有代码。

在这种情况下,顶级代码是 if 块。 __ name __ 是一个内置变量,其值为当前模块的名称。但是,如果直接运行模块(如上面的 myscript.py ),则 __ name __ 将设置为字符串" __ main __" 。因此,您可以通过测试

来测试您的脚本是直接运行还是通过其他方式导入
if __name__ == "__main__":
    ...

如果您的脚本被导入到另一个模块中,它的各种函数和类定义将被导入并且它的顶级代码将被执行,但是的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 __"

__ 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 __'] 设置为模块的名称。此外,导入时,模块中的所有代码都在运行。当 if 语句求值为 False 时,不会执行此部分。

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

如您所见,在执行文件时,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()

通过上述内容,您的代码仅当您将其作为主模块运行(或有意从另一个脚本调用它)时才会执行。

更好的方法

不过,有一种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()

这个习惯用法也可以在 Python 文档的解释中找到 __main__ 模块。 该文本指出:

该模块表示解释器主程序执行的(否则匿名)范围 - 从标准输入,脚本文件或交互式提示中读取命令。正是在这种环境中,惯用的“条件脚本”节使脚本运行:

if __name__ == '__main__':
    main()

如果__name__ ==" __ main __" 是使用 python myscript.py 之类的命令从命令行运行脚本时运行的部分

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

__name__ 是一个全局变量(在Python中,global实际上意味着 模块级) 存在于所有命名空间中。它通常是模块的名称(作为 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__": 是解释器的测试,以确定它是否正在解释/解析最初执行的“home”脚本,或者是否正在暂时查看另一个(外部)脚本。这为程序员提供了灵活性,使脚本在直接执行和直接执行时的行为有所不同。外部调用。

让我们逐步完成上面的代码以了解发生了什么,首先关注未缩进的行以及它们在脚本中出现的顺序。记住该功能 - 或 def - 块在被调用之前不会自行执行任何操作。如果口译员自言自语,他可能会说:

  • 打开 xy.py 作为“home”文件;叫它 "__main__" 在里面 __name__ 多变的。
  • 导入并打开文件 __name__ == "ab.py".
  • 哦,一个函数。我会记住这一点。
  • 好的,功能 a();我刚刚了解到这一点。印刷 'ab 文件中的函数'.
  • 文件结束;回到 "__main__"!
  • 哦,一个函数。我会记住这一点。
  • 另一个。
  • 功能 x();好的,正在打印'外围任务:可能在其他项目中有用'.
  • 这是什么?一个 if 陈述。好了,条件已经满足了(变量 __name__ 已设置为 "__main__"),所以我将输入 main() 函数并打印 '主功能:这就是行动的地方'.

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

为什么要实施这个?

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

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

但代码没有它就可以工作

恩,那就对了。这些独立的功能 从不包含在 a 中的内联脚本中调用 main() 功能。如果您习惯于(就像我一样,在编程的早期学习阶段)构建完全满足您需要的内联脚本,并且如果您再次需要该操作,您将尝试再次弄清楚它.. 。好吧,您不习惯代码的这种内部结构,因为它的构建更复杂,并且阅读起来不那么直观。

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

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

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

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

默认情况下(当模块作为main运行,而不是导入时) __ name __ 变量设置为&quot; __ main __&quot; ,当它被导入时<代码> __ name __ 变量将获得不同的值,最可能是模块的名称('M')。 这有助于将模块的不同变体一起运行,并将它们的特定输入和输出分开。输出语句以及是否有任何测试用例。

简而言之,请使用此 if __name__ ==&quot; main&quot; '块来阻止(某些)代码在导入模块时运行。

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

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

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

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

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

简单地说, __ 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 __ 告诉我们哪个代码是'main'模块。 这很好,因为你可以只编写代码而不必担心C / C ++中的结构问题,如果文件没有实现'main'函数那么它就不能被编译成可执行文件,如果是的话,它不能用作图书馆。

假设您编写的Python脚本可以执行一些非常棒的操作,并且您可以实现一系列对其他用途有用的函数。如果我想使用它们,我只需导入您的脚本并在不执行程序的情况下使用它们(假设您的代码仅在中执行,如果__name__ ==&quot; __ main __&quot;:上下文)。而在C / C ++中,您必须将这些部分分成一个单独的模块,然后包含该文件。想象下面的情况;

中的复杂导入

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

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

以交互方式运行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 __ 属性是否为&quot; __ main __&quot; 。换句话说,如果程序本身被执行,该属性将是 __ main __ ,因此程序将被执行(在这种情况下是 main()函数。)

但是,如果模块使用了Python脚本,那么 if 语句之外的任何代码都将被执行,所以如果\ __ name__ ==&quot; \ __ main __&quot; 仅用于检查程序是否用作模块,因此决定是否运行代码。

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

  

什么是 __ name __

__ name __ DunderAlias - 可以被认为是全局变量(可从模块访问),其工作方式与 global相似

它是一个字符串(如上所述的全局),由 type(__ name __)(产生&lt; class'str'&gt; )表示,并且是内置的 Python 3 Python 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 __ :Python中的每个模块都有一个名为 __ name __ 的特殊属性。 它是一个内置变量,它返回模块的名称。

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

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

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

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

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

我并不是说你应该在生产代码中使用它,但它可以说明没有什么“魔法”。关于 if __name__ =='__ main __'。在Python文件中调用main函数是一个很好的约定。

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

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

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

如果Python将此源代码文件作为主程序(即您运行的文件)加载,则会将此文件的特殊 __ name __ 变量设置为值&quot; __ 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 ”在那个特定的例子中。

希望这会有所帮助。

如果__name__ ==&quot; __ main __&quot;:基本上是顶级脚本环境,它指定解释器('我首先执行的优先级最高')。

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

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

原因

if __name__ == "__main__":
    main()

主要是为了避免导入锁定 直接导入代码会产生的问题。您希望 main()在您的文件被直接调用时运行(即 __ name__ ==&quot; __ main __&quot; 情况),但如果您的代码已导入,则导入器具有从真正的主模块输入代码以避免导入锁定问题。

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

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

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

  1. 导入操作实际上运行了可以在“a”中运行的所有内容

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

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

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

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

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

考虑:

print __name__

上面的输出是 __ main __

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

以上陈述属实,并打印“直接方法”。假设他们在另一个类中导入了这个类,它不会打印“direct method”,因为在导入时,它会将 __ name__设置为等于“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

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

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

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

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

如果此.py文件是由其他.py文件导入的,则代码位于“if语句”下面。不会被执行。

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

通常用于测试。

创建一个文件 a.py

print(__name__) # It will print out __main__
只要该文件直接运行

__ name __ 总是等于 __ main __ ,表明这是主文件。

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

import a  # Prints a

运行它。它会打印 a ,即导入的文件名。

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

# Code to be run when imported into another python file

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

如果名称 =='主要':

我们经常看到 __ name__ =='__ main __':

检查是否正在导入模块。

换句话说, if 块中的代码只有在代码直接运行时才会执行。这里直接意味着 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文件,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是运行的主文件),那么只有代码被执行。

只是它是 C 编程语言中 main 函数运行文件的入口点。

python中的每个模块都有一个名为 name 的属性。模块直接运行时, name 属性的值为' main '。否则, name 的值是模块的名称。

简短解释的小例子。

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

现在假设我们从其他脚本调用上面的脚本

#script 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中的循环 name 将不会执行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top