首页 > 编程语言 >Python 中的 if __name__ == '__main__' 该如何理解

Python 中的 if __name__ == '__main__' 该如何理解

时间:2024-03-02 20:44:05浏览次数:37  
标签:__ name Python py 模块 main 运行

结论

if __name__ == '__main__' 我们简单的理解就是: 如果模块是被直接运行的,则代码块被运行,如果模块是被导入的,则代码块不被运行

程序入口

对于很多编程语言来说,程序都必须要有一个入口,比如 C,C++,以及完全面向对象的编程语言 Java,C# 等。如果你接触过这些语言,对于程序入口这个概念应该很好理解,C 和 C++ 都需要有一个 main 函数来作为程序的入口,也就是程序的运行会从 main 函数开始。同样,Java 和 C# 必须要有一个包含 Main 方法的主类来作为程序入口。

而 Python 则有不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。

一个 Python 源码文件除了可以被直接运行外,还可以作为模块(也就是库)被导入。不管是导入还是直接运行,最顶层的代码都会被运行(Python 用缩进来区分代码层次)。而实际上在导入的时候,有一部分代码我们是不希望被运行的。

举一个例子来说明一下,假设我们有一个 const.py 文件,内容如下:

PI = 3.14

def main():
    print "PI:", PI

main()

我们在这个文件里边定义了一些常量,然后又写了一个 main 函数来输出定义的常量,最后运行 main 函数就相当于对定义做一遍人工检查,看看值设置的都对不对。然后我们直接执行该文件(python const.py),输出:

PI: 3.14

现在,我们有一个 area.py 文件,用于计算圆的面积,该文件里边需要用到 const.py 文件中的 PI 变量,那么我们从 const.py 中把 PI 变量导入到 area.py 中:

from const import PI

def calc_round_area(radius):
    return PI * (radius ** 2)

def main():
    print "round area: ", calc_round_area(2)

main()

运行 area.py,输出结果:

PI: 3.14
round area:  12.56

可以看到,const 中的 main 函数也被运行了,实际上我们是不希望它被运行,提供 main 也只是为了对常量定义进行下测试。这时,if __name__ == '__main__' 就派上了用场。把 const.py 改一下:

PI = 3.14

def main():
    print "PI:", PI

if __name__ == "__main__":
    main()

然后再运行 area.py,输出如下:

round area:  12.56

再运行下 const.py,输出如下:

PI: 3.14

这才是我们想要的效果。

if __name__ == '__main__' 就相当于是 Python 模拟的程序入口。Python 本身并没有规定这么写,这只是一种编码习惯。由于模块之间相互引用,不同模块可能都有这样的定义,而入口程序只能有一个。到底哪个入口程序被选中,这取决于 __name__ 的值。

name

__name__ 是内置变量,用于表示当前模块的名字,同时还能反映一个包的结构。来举个例子,假设有如下一个包:

a
├── b
│   ├── c.py
│   └── __init__.py
└── __init__.py

目录中所有 py 文件的内容都为:

print __name__

我们执行 python -c "import a.b.c",输出结果:

a
a.b
a.b.c

由此可见,__name__ 可以清晰的反映一个模块在包中的层次。其实,所谓模块名就是 import 时需要用到的名字,例如:

import tornado
import tornado.web

这里的 tornado 和 tornado.web 就被称为模块的模块名。

如果一个模块被直接运行,则其没有包结构,其 __name__ 值为 __main__。例如在上例中,我们直接运行 c.py 文件(python a/b/c.py),输出结果如下:

__main__

所以,if __name__ == '__main__' 我们简单的理解就是: 如果模块是被直接运行的,则代码块被运行,如果模块是被导入的,则代码块不被运行

实际上,这个问题还可以衍生出其他的一些知识点,例如 __main__.py 文件与 Python 的 -m 参数。

main.py 文件与 python -m

Python 的 -m 参数用于将一个模块或者包作为一个脚本运行,而 __main__.py 文件则相当于是一个包的”入口程序“。

首先我们需要来看看 python xxx.pypython -m xxx.py 的区别。两种运行 Python 程序的方式的不同点在于,一种是直接运行,一种是当做模块来运行。

先来看一个简单的例子,假设有一个 Python 文件 run.py,其内容如下:

import sys
print sys.path

我们用直接运行的方式启动(python run.py),输出结果(为了说明问题,输出结果只截取了重要部分,下同):

['/home/huoty/aboutme/pythonstudy/main', ...]

然后以模块的方式运行(python -m run.py):

['', ...]
/usr/bin/python: No module named run.py

由于输出结果只列出了关键的部分,应该很容易看出他们之间的差异。直接运行是把 run.py 文件所在的目录放到了 sys.path 属性中。以模块方式运行是把你输入命令的目录(也就是当前工作路径),放到了 sys.path 属性中。以模块方式运行还有一个不同的地方是,多出了一行 No module named run.py 的错误。实际上以模块方式运行时,Python 先对 run.py 执行一遍 import,所以 print sys.path 被成功执行,然后 Python 才尝试运行 run.py 模块,但是,在 path 变量中并没有 run.py 这个模块,所以报错。而正确的运行方式,应该是 python -m run.

这个例子并不能明显的说明问题。接着我们来看看 __main__.py 的作用。

仍然先看例子,有如下一个包:

package
├── __init__.py
└── __main__.py
  • init.py
import sys
print "__init__"
print sys.path
  • main.py
import sys
print "__main__"
print sys.path

python -m package 运行结果:

__init__
['', ...]
__main__
['', ...]

python package 运行结果:

__main__
['package', ...]

然后我们来总结一下:

  • 1、 加上 -m 参数时会把当前工作目录添加到 sys.path 中,而不加时则会把脚本所在目录添加到 sys.path 中
  • 2、 加上 -m 参数时 Python 会先将模块或者包导入,然后再执行
  • 3、 main.py 文件是一个包或者目录的入口程序。不管是用 python package 还是用 python -m package 运行时,main.py 文件总是被执行。

后序

Python 的确是简单的,优雅的,但也有很多问题是不太容易理解的,例如很多高级的特性,像元类、生成器表达式、描述符、协程等。Python 并没有在太多的地方规定要如何如何,很多的用法只是惯用法,例如 self 和本文讨论的内容。这些用法或是为了让代码看起来更优雅,或是前人的经验。使用 Python 是有无限可能的,你可以写出很多简洁优雅的代码。

标签:__,name,Python,py,模块,main,运行
From: https://www.cnblogs.com/guanghui-hua/p/18049206

相关文章

  • 基于键级别的背书策略
    背书策略主要是针对定义交易是否合法的判断条件。一般的策略以主体形式进行呈现。在hyperledgerfabric中共有四种合法角色:member,admin,client,peer一般使用的背书策略语法:Expression(E[,E...])基于键值的背书策略shim包提供了一些函数可以设置背书策略,其具体如下所示。......
  • 2024AcWing蓝桥杯集训·每日一题-前缀和
    1.[AcWing562.壁画]题目描述Thanh想在一面被均分为\(N\)段的墙上画一幅精美的壁画。每段墙面都有一个美观评分,这表示它的美观程度(如果它的上面有画的话)。不幸的是,由于洪水泛滥,墙体开始崩溃,所以他需要加快他的作画进度!每天Thanh可以绘制一段墙体。在第一天,他可以自由的......
  • 基于四叉树的图像分割算法matlab仿真
    1.算法运行效果图预览   2.算法运行软件版本matlab2022a 3.算法理论概述        图像分割是计算机视觉和图像处理中的一项关键技术,旨在将图像划分为多个具有相似性质的区域。基于四叉树的图像分割算法是一种有效的分割方法,它通过递归地将图像划分为四个子......
  • 56. 合并区间(中)
    目录题目法一、排序+讨论法二、简洁题目以数组intervals表示若干个区间的集合,其中单个区间为intervals[i]=[starti,endi]。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。示例1:输入:intervals=[[1,3],[2,6],[8,10],[15,1......
  • 数学之概率题目总结
    前言如有错误,欢迎各位dalao指出。前置芝士:概率T1题目传送门可以看见,标签是入门,一定非常水。显然,要让小D获胜,我们只需要选出\(max(v,w)\rightarrow6\)这一段的任意一个值即可获胜,注意特判一下\(max(v,w)>6\)的情况就行了。还是比较水。T2题目传送门老师抽我起......
  • pod为什么会被驱逐及如何避免pod被驱逐导致的服务中断
    Pod被驱逐的原因主要有以下几点:资源不足:当节点资源(如CPU、内存、存储等)不足以满足Pod的资源需求时,调度器会选择将其中一个或多个Pod驱逐出节点,以便在资源有限的节点上安排新的Pod。超出资源限制:Pod可以指定资源上限,如CPU和内存的限制。如果Pod使用的资源超过了所指定的限制,该Po......
  • Python环境安装与配置
    1.浏览器输入python官方网站打开2.选择downloads后,再选择电脑的操作系统,如:Windows3.根据自己的电脑选择合适的版本,如:3.12版4.选择下载好的版本,鼠标右键选择以管理员身份运行5.勾选AddPythontoPATH,点击Customizeinstallation(自定义安装)6.点击next7.选中installPython3.......
  • The 2023 ICPC Asia Macau Regional Contest (The 2nd Universal Cup. Stage 15: Maca
    Preface最幽默的一集这场开局感觉三个人都有点发昏了,前3h30min就出了两个题,有种要打铁了的感觉后面想着干脆保个银牌稳扎稳打吧,没想到后面1h连着出了四个题成功冲到银首最后徐神好像也会G这个博弈了,如果前面不犯病的话感觉还真有机会出7题的说A.(-1,1)-Sumplete徐神基本被......
  • 浅谈差分
    1.前言前置芝士:基本树上操作,lca。(用于树上差分。)如有错误,欢迎各位大佬指出。(顺便复习一下远古算法。)2.什么是差分我们先给定一个数组\(a\),长度为\(n\),我们可以构造一个差分数组\(b\),使得对于任意的\(i(1\lei\len)\),\(\displaystyle\sum_{j=1}^{i}b_j=a_i\)。那......
  • 解决ssh链接报错问题
    在使用ssh连接时出现报错,如下┌──(kali㉿kali)-[~]└─$sshuser@10.10.171.15Unabletonegotiatewith10.10.171.15port22:nomatchinghostkeytypefound.Theiroffer:ssh-rsa,ssh-dss意思就是找不到匹配的主机密钥类型,需要手动......