热门标签:
Q:

如果__name__=="__main__":do怎么办?

给定以下代码,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))
原网址
A:

简短回答

它是样板代码,可以保护用户在不打算时意外调用脚本。 以下是从脚本中省略guard时的一些常见问题:

  • 如果您在另一个脚本中导入没有guardless脚本(例如import my_script_without_a_name_eq_main_guard),那么第二个脚本将触发第一个脚本在导入时运行使用第二个脚本的命令行参数。 这几乎总是一个错误。

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

长答案

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

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

  • 它设置了一些像__name__这样的特殊变量,然后

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

让我们看看这是如何工作的,以及它如何与您关于我们在Python脚本中总是看到的__name__检查的问题相关联。

代码示例

让我们使用一个稍微不同的代码示例来探索导入和脚本的工作方式。 假设以下内容在名为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文件(以及搜索其他一些变体),并且在执行该模块之前,它将将来自import语句的名称"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 functionA"

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

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

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

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

只有当你的模块是主程序时

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

只有当你的模块被另一个

导入时
    如果你的模块不是主程序,而是由另一个程序导入的,那么__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.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

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.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

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

所有回答

共 29 条

author avatar

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

python myscript.py

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

在这种情况下,顶层代码是一个if块。 __name__是一个内置变量,它计算当前模块的名称。 但是,如果一个模块直接运行(如上面的myscript.py),那么__name__被设置为字符串"__main__"。 因此,您可以通过测试

来测试您的脚本是直接运行还是由其他东西导入
if __name__ == "__main__":
    ...

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

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

author avatar

__name__变量(恕我直言)最简单的解释如下:

创建以下文件。

# 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并正在运行。

author avatar

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循环或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()
author avatar

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

author avatar

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

这里有很多不同的代码机制,"如何",但对我来说,在我理解"为什么"之前,这些都没有意义。 这应该对新程序员特别有帮助。

拿文件"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语句在import时立即运行模块,因此 ab 的操作在 xy 的其余部分之前执行。

解释器跟踪哪些脚本正在使用 __name__ 运行。 当你运行一个脚本时--不管你给它命名了什么--解释器调用它 "__main__" ,使它成为运行外部脚本后返回的主脚本或"主脚本"脚本。

"__main__" 脚本调用的任何其他脚本都将其文件名指定为其 __name__ (例如 __name__ == "ab.py" )。 因此,行 if __name__ == "__main__": 是解释器的测试,以确定它是在解释/解析最初执行的"home"脚本,还是暂时偷看另一个(外部)脚本。 这使程序员可以灵活地让脚本在直接执行而不是外部调用时表现不同。

让我们通过上面的代码来了解发生了什么,首先关注未注释的行以及它们在脚本中出现的顺序。 请记住,函数-或 def -块在被调用之前不会自己做任何事情。 解释器如果喃喃自语的话会说些什么:

  • 打开xy.py 作为'home'文件;在 __name__ 变量中调用它 "__main__"
  • 使用 __name__ == "ab.py" 导入并打开文件。
  • 哦,一个函数。 我会记住的。
  • 好的,function a() ;我刚刚学会了这一点。 在ab文件中打印' 函数'。
  • 文件结束;返回 "__main__"
  • 哦,一个函数。 我会记住的。
  • 再来一个。
  • Function x() ;ok,printing' peripheral task:might be used in other projects '.
  • 这是什么? 一个 if 语句。 那么,条件已经满足(变量 __name__ 已设置为 "__main__" ),所以我将进入 main() 函数并打印' 主函数:这是动作的位置 '。

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

为什么要实现这一点?

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

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

但是代码没有它就能工作

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

但这是一个脚本,可能不能在外部调用它的函数,因为如果它这样做,它将立即开始计算和分配变量。 如果你试图重新使用一个函数,那么你的新脚本与旧脚本密切相关,因此会有冲突的变量。

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

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

author avatar

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

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

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

author avatar

如果模块作为脚本调用,则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')

第一种可能性:Importmy_test_module.pyin another module

# 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中的顶级my_test_module语句。


第二种可能性:Invokemy_test_module.pyas a script

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

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'

为了更全面的解释,你可以阅读if __name__ == '__main__'在Python中做什么。

author avatar

简而言之,__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项目中,除非它被专门编译为库。 现在想象一下Python:

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

author avatar

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

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

...

if __name__ == '__main__':
    
...

块A和B在我们运行 x.py 时运行。

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

author avatar

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

  1. import aaction实际上运行所有可以在python a.py中运行的,意味着python a.py中的每一行

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

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

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

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

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

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

author avatar

当您以交互方式运行Python时,local__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.
author avatar

考虑一下:

if __name__ == "__main__":
    main()

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

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

author avatar

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

什么是__name__

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

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

其中:

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

解释器:

>>> 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__,允许这样做。

你应该看到,where__name__,它是主文件(或程序)将总是返回__main__,如果它是一个模块/包,或者任何正在运行其他Python脚本的东西,将返回它起源的文件的名称。

实践:

作为一个变量意味着它的值可以被复盖("can"并不意味着"应该"),复盖__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__事物的行为变得更加清晰:

Anif是一个包含代码块的流控制语句,如果给定的值为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

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

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

author avatar

我认为最好在深度和简单的话中打破答案:

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

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

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

author avatar

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

它可以写在几个方面。 另一个是:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

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

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

author avatar

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

希望这能有所帮助。

author avatar

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

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

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

考虑一下:

print __name__

上述输出为__main__

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

上述语句为true,打印"直接方法"。 假设如果他们在另一个类中导入了这个类,它不会打印"直接方法",因为在导入时,它会设置__name__ equal to "first model name"

author avatar

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

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

author avatar

原因是

if __name__ == "__main__":
    main()

主要是为了避免导入锁问题,因为直接导入代码。 如果您的文件被直接调用(这是__name__ == "__main__"案例),您希望__name__ == "__main__"运行,但如果您的代码是导入的,那么导入器必须从true main模块输入您的代码以避免导入锁问题。

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

author avatar

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

小例子来简单解释。

脚本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 looptest.py将不会执行。

author avatar

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

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

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

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

author avatar

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

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

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

author avatar

用简单的话来说:

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

但是,如果你想导入你的python文件'example1.py'作为与另一个python文件一起工作的模块说'example2.py',if __name__ == "__main__":下的代码不会运行或产生任何效果。

author avatar

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

如果你导入这个文件,说A到文件B,并执行文件B然后文件A中的if __name__ == "__main__"变成false,所以它打印你看不到我

b

author avatar

ifname=='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__
author avatar

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

稍微详细一点,假设你有一个简单的脚本 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 ,但如果你一开始不打算这样做,这个版本实际上更好,因为它更简单,更清晰。

如果你 do 希望能够 import fib ,第一个版本也是无用的,因为有用的代码在你 import 这个文件时不会运行的部分(在这种情况下 __name__ 不会是 "__main__" )。 在这种情况下,适当的设计是重构代码,以便有用的部分在一个函数中,你可以在你想要的时候运行。

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 (或者,也许更好,重构 main return lock ,并让调用者在自己的局部变量中捕获值)。

author avatar

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

假设你有两个Python文件,a.py 和b.py.现在,a.py 进口产品b.py。我们经营a.py 文件,其中"导入b.py"代码首先执行。 在其余时间之前a.py 代码运行,文件中的代码b.py 必须完全运行。

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

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

相似问题