Python中的if __name__ == “__main__“ 的全面解释

本文详细介绍了Python中`if __name__ == __main__`语句的作用、工作原理以及何时与如何使用。它用于区分脚本直接运行和作为模块导入的情况,允许在脚本执行时执行特定代码。最佳实践建议将其放置在文件底部,仅在需要时使用,以保持代码整洁。此外,文中还讨论了避免滥用此语句的情况和编写测试代码的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要参考文章: What Does if __name__ == "__main__" Do in Python? – Real Python有兴趣的可以参考原文。
学习一段时间Python后,在阅读别人的代码时,经常会看到 if __name__ == "__main__”这样的语句出现。这个语句是用来干什么的?本文中对这个进行一个探讨。
这是一个条件判断语句,如果条件满足,就进入下面的语句。简单来说,该语句用来当文件当作脚本运行时候,就执行代码;但是当文件被当做Module被import的时候,就不执行相关代码。
也就是说如果你需要把代码放在一个文件中,在 if __name__ == "__main__”里面放的代码,就只有在该文件被当作脚本文件执行的时候才会起作用。
比如下面的例子:
 
# print_hello.py

def printHello():
    print(“hello”)

if __name__ == “__main__"
    print(“in if __name__ == __main__ block”)
在上面的代码中,可以运行
>>>python print_hello.py
in if __name__ == __main__ block
如果用python来执行该文件,那么in if __name__ == “__main__” 条件就会满足,就会打印出
in if __name__ == __main__ block语句。
但是如果将print_hello.py文件当作module导入,情况如下:
>>>from print_hello import printHello
>>>printHello()
Hello
可以看到,在这种情况下,if __name__ == “__main__” 下面的代码是没有被激活执行的。
因此可以看到,我们可以将代码放到if __name__ == “__main__”,来适应不同的使用场景。
这段代码的工作原理
从上面的例子,可以看到if __name__ == “__main__”主要就是一个条件语句
  • 当该条件语句为True的时候,该语句下的缩进语句代码,就会执行
  • 当该条件语句为False的时候,该语句下的缩进语句代码,就会被Python解析器跳过
那么需要考虑的是什么时候if __name__ == “__main__”会为True,也就是__name__ 变量会等于“__main__”?__name__变量是一个Python的Module的全局变量,Python解析器会在执行过程中设置该变量。当Python解析器将代码当作顶层模块运行的时候,__name__变量就会被赋值为“__main__”。
所谓的顶层模块,就是指第一个运行的用户定义的Python的模块。这个模块由于是第一个执行的,因此在该模块运行中,将会由此模块导入imports所有其他的别的相关依赖模块。因此该模块就被当作顶层模块。
为了很好的理解这个,可以简单的用一个例子来说明。
# showname.py
print(__name__, type(__name__))
该语句打印__name__
$ python show name.py
__main__ <class ’str’>
可以看到如果当作脚本来执行就被设置成了__main__。
>>> import showname
showname <class ’str’>
在这个例子中,python在import过程中,执行了showname。py文件全局命名空间中的代码,并且将结果打印在控制台中,也就是打印了print(__name__, type(__name__))
如果是当作module导入的时候,该名字就被设置成了showname,该模块的名字。
从上面的内容已经说明了,python总是把最顶层的模块的__name__设置成main,因此可以做如下试验:
>>> import showname
showname <class ’str’>
>>> __name__
'__main__'
>>> showname.__name__
'showname'
可以看到和上面介绍的知识点是一致的。总结如下:
  • 最顶层的__name__,将会被设置成了__main__
  • 导入的模块中的__name__就被设置成了模块的名称
因此也可以用if __name__ == “__main__”来判断你的模块代码是不是被当作最顶层模块在使用。
知道了运行原理,再次回到在什么情况下需要使用if __name__ == "__main__”语句,该语句可以用来干什么?
根据这个特性,可以用来对脚本中的函数进行一些输入参数获取。比如在模块中,有一些函数需要输入一些参数,那么当该模块被当作顶层模块执行时候,那么可以通过if __name__ == "__main__”语句来获取输入,并且调用相关的函数,如果该函数被当作模块来调用的时候,函数的输入可以由其他导入的模块来进行输入给定。
什么时候需要避免使用if __name__ == "__main__”语句。
有些时候可以用来屏蔽掉执行测试的部分代码。比如下面的例子:
如果该模块被执行,可以用来执行测试用例,否则就当作一个模块导入,测试不会被执行。
import unittest
def add(a: int, b: int) -> int:
    return a + b
class TestAdder(unittest.TestCase):
    def test_add_adds_two_numbers(self):
        self.assertEqual(add(1, 2), 3)
if __name__ == "__main__":
    unittest.main()
但是这种方式不太建议,在比较规模项目的测试中,是可以这么做,但是如果代码量一大,这种将代码和测试混在一个文件的方式,不太方便代码管理。一般应该是将测试代码写在另外一个文件中。同时这也要求将 unittest模块在代码模块中导入,这也不是一个很好的实现。
另外一个不好的使用例子是用来包含一些模块使用信息,当用户导入该模块的时候,使用信息不会被执行,但是当当作脚本运行的时候,就可以打印出使用信息。这其实也不是一个很好的实践。如果是用来打印使用信息,可以用别的更好的方法(比如编写详细的docstrings)。
第三种情况是纯脚本情况:如果你要写的代码就是一个脚本,那么你就直接写代码在全局空间中即可,不要再放到if __name__ == “__main__”下,这样做意义不大。
最后讲一下使用if __name__ == “__main__"的最佳实践。
首先这个语句只是一个判断语句,因此该语句可以被放到文件的任何地方,也可以多次使用。但是比较好的建议是大部分情况,该语句只在文件中出现一次,并且放到文件的最后。这样可以似的代码变得比较整洁,逻辑也会清晰很多。该语句放到最后还有一个好处,就是确保所有需要使用的函数或者变量都已经在前面定义好了。
但是在某些情况,也可以多次的使用if __name__ == "__main__”语句。
比如分情况导入其他模块,见如下例子:
if __name__ == "__main__":
    import sys
def echo(text: str, repetitions: int = 3) -> str:
    """Imitate a real-world echo."""
    echoed_text = ""
    for i in range(repetitions, 0, -1):
        echoed_text += f"{text[-i:]}\n"
    return f"{echoed_text.lower()}."
if __name__ == "__main__":
    text = " ".join(sys.argv[1:])
    print(echo(text))
在该例子中,可以利用该条件语句,是的不必要的导入一些模块。过多的解释就不在赘述。
另外的一个好的代码风格就是if __name__ == "__main__”下面的代码应该尽可能的少,如果需要放比较多的代码,
那么就应该另外定义个main函数来包含这些代码。
比如如下代码:
import sys
def echo(text: str, repetitions: int = 3) -> str:
    """Imitate a real-world echo."""
    echoed_text = ""
    for i in range(repetitions, 0, -1):
        echoed_text += f"{text[-i:]}\n"
    return f"{echoed_text.lower()}."
def main() -> None:
    text = " ".join(sys.argv[1:])
    print(echo(text))
if __name__ == "__main__":
    main()
后记
很多讨论将python的if __name__ == “__main__"和其他语言的入口函数main()做比较,然后得出结论说python的语法太不简洁。其实事情并不是这样的,if __name__ == "__main__"只是一个判断语句,不是程序的入口点。
python在演化过程中,对该用法的讨论也进行过很多次,但是一直也没有对这个用法有太多改变,主要原因有如下几点:
  • 这个语句已经很短了:很多其他的建议节约不了几行代码
  • 使用场景不多:只建议在需要将一个脚本文件运行同时也能够当作模块导入的时候,需要用到,其他情况不建议经常使用。
  • 暴露了复杂性:让python使用人员,能够了解python的背后的变量和函数,这样可以更好的理解python的实现。
  • 可以向后兼容。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老猿讲编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值