谈谈Python的模块加载与内置属性__name__的关系

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」。

正式的Python专栏第76篇,同学站住,别错过这个从0开始的文章!

前篇学委分享了一个进程池,里面特别谈到,必须要在’__main__‘代码块内或者内部调用其他模块来创建进程池,否则就会报错。

那么背后是什么原因呢?我认为可以分为两篇文章可以解释的很清楚。

本篇为独立一篇,我们看看__name__这个内置属性。

第一点 脚本/模块内 可执行代码 加载的时候必然被执行

严格来说’__main__‘代码块,并非脚本的入口,因为python程序运行时是从模块顶行开始,逐行进行翻译执行的。所以 可执行代码(表达式或者函数调用等)一旦被解释器加载,立马就执行了,根本不必等到放到’__main__‘代码块内。

这是第一点,也是python编译器的原理。如果需要更多解释,学委后面围绕python编译器运行的源码展再做分享,但不在本文范围中。

第二点 主动加载模块时,模块的__name__属性会被设置为’__main__‘

python解释器在直接运行一整个脚本/模块的时候,设置了__name__这个模块内置属性(内置变量),把它的值设置为’__main__‘。

这里说的‘主动加载’其实是相对的,学委为了解释方便提出的概念,更准确的是,执行运行模块。一个python模块就是代码集合,它本身没有能动性的,这个读者们必须搞清楚。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/2/27 10:53 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : lib01.py
# @Project : DeepDivePython

def demo():
    print("demo in lib:", __name__)

print("leixuewei")
demo()

if __name__ == "__main__":
    print("execute in main block")
复制代码

如下图所示,我们看到使用:venv/bin/python <lib01.py\的路径>,这个本质上是用编译器运行python脚本。

这里模块lib01._name_属性的值变成了’__main__‘,最后打印了‘execute in main block’。

屏幕快照 2022-02-27 下午11.24.08.png

第三点 模块被动加载时,内置属性__name__属性的值变成模块名

我们在import一个模块的时候,除了’__main__‘代码块内的代码是不会被运行的,其他模块内如果出现可执行的代码,则无碍,它们照常继续被加载执行。

如下面代码所示

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/2/27 10:55 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : call_lib01.py
# @Project : DeepDivePython
import lib01

lib01.demo()
复制代码

如下图所示,这里打印了三句,前两句是加载lib01的过程中一边解释执行的输出。

第三句子为:call_lib01.py的lib01.demo()调用的输出结果。

屏幕快照 2022-02-27 下午10.57.02.png

因为lib01的内置属性__name__属性的值变成了’lib01‘了。

也就是前面学委分享的大多数demo代码都是直接在脚本内调用方法执行的。

结语

本文就分享3点,希望读者都能理解,吃透!这个是python编程的基础。

喜欢Python的朋友,请关注学委的 Python基础专栏 or Python入门到精通大专栏

持续学习持续开发,我是雷学委!
编程很有趣,关键是把技术搞透彻讲明白。
欢迎关注微信,点赞支持收藏!

猜你喜欢

转载自juejin.im/post/7069412260350787598