50、Python之模块和包:入口文件和模块,Python项目组织的最佳实践

引言

其实在项目中每一个Python源文件,都可以作为入口文件,也都可以作为模块被导入。那么一个.py文件,被当做模块导入,或者被当作入口文件被Python解释器执行时,有什么区别呢?一个项目中代码文件多起来,该如何组织、管理项目的代码才更加合理呢?今天这篇文章,我们就这两个问题进行一个系统的解答。

本文的主要内容有:

1、模块的内置变量

2、入口文件

3、项目代码组织的最佳实践

模块的内置变量

在前面介绍模块的文章中,我们通过代码查看过模块的全局命名空间,其中,有几个以__打头的变量,之前暂时略过了,今天我们来看下这几个特殊的变量,主要是:

1、__name__

2、__file__

3、__package__

4、__doc__

5、__cached__

直接看代码:

模块m1.py的代码:

"""这里是模块m1的docstring"""
a = 10
b = 20


def add(n1, n2):
    return n1 + n2


print("这里是模块m1")

入口文件的代码:

"""这里是入口文件"""
import m1
from rich.pretty import pprint as print

print(m1.__name__)
print(m1.__file__)
print(m1.__package__)
print(m1.__doc__)
print(m1.__cached__)

print('这里是入口文件的部分')
print(__name__)
print(__file__)
print(__package__)
print(__doc__)
print(__cached__)

执行结果

49c8dad07f8f8f06cb0584b937584143.jpeg
从执行结果中可以看出:

1、模块被导入时,顶级代码块中的任何代码都会执行一遍,所以,会看到有输出“这里是模块m1”。

2、被导入的模块中的__name__变量为模块名,需要补充说明的是,如果有包,会是带包的全限定名。

可以通过代码验证,比如有如下代码结构:

f895e240e9d0a2b86f4ad24ce4b289c7.jpeg
入口文件main_1.py的代码:

"""这里是入口文件"""
from package1 import m2

print(m2.__name__)

运行结果会是输出“package1.m2”

3、入口文件中的__name__变量会被Python解释器置为__main__,而不再是模块的全限定名。

4、__file__都是模块所对应的.py文件的绝对路径。

5、__package__,当是被导入模块时,有所属包时,则存储包名,否则为空字符串“”。当是入口文件是,这个变量被置为None。

6、__doc__是模块中的docstring的内容,docstring的通常写法是在模块的开头,以三个双引号括起来的关于模块的说明文档。如果没有,则为None。

7、__cached__,如果是导入的模块,之前已经提及过,一定会先编译为字节码文件,下次执行时,需要导入该模块,可以提高速度。当是入口文件时,一定不会进行字节码编译的操作,所以被置为None。

入口文件

由于任意一个.py文件,既可以作为一个模块,被其他.py文件导入,也可以作为入口文件,直接交由Python解释器执行。

所以,任意一个.py文件都可能,也都可以是入口文件。

基于上面关于模块的__name__内置变量的说明,我们可以知道,基于这个变量的取值,我们就可以在代码运行过程中,判断这个.py文件,是作为入口文件被执行的,还是作为模块被导入时执行的。

约定俗成的写法,其实之前已经反复用过,就是:

if __name__ == '__main__':

通过这个语句构建一个代码块,将代码切分为顶级代码块和入口代码块。

一个.py文件,即便后续更多地作为模块被导入来执行,但是,在编写过程中,也会写一些测试代码来验证模块的代码逻辑,这些测试代码如果放在顶级代码块中,就会在导入时被执行,比如前面的print()语句。

如果只想在测试模块时执行,模块被导入时,不想要执行,就可以改造为:

"""这里是模块m1的docstring"""
a = 10
b = 20


def add(n1, n2):
    return n1 + n2


if __name__ == '__main__':
    print("这里是模块m1")

虽然,在模块中通过__name__的判断,在代码块放置了一些模块的测试代码。

但是,真正的入口文件,应该是作为项目的启动点(Entry Point),通常是项目的主文件,通常可以命名为main.py或者__main__.py,当然,其他文件名也是可以的,只要方便辨识即可。

入口文件通常用于项目的执行环境初始化(配置、资源等)、调用其他模块的函数或者类,以及控制程序的执行流程。

项目代码组织的最佳实践

虽然Python给予开发者极大的自由度,但是,在开发相对复杂的项目、涉及到团队协作的时候,还是有些在项目代码组织上的最佳实践,应当参考的。

1、模块的命名和组织

模块命名应尽量清晰,模块尽量做到高内聚、低耦合,从而更大程度的提升代码的复用程度,模块较多且有层次的,应该使用包(Package)来进行层次化的组织与管理。

2、入口文件设计

一个项目应当尽量有一个明确的启动入口文件,尽量放置在项目的跟目录中,降低模块导入的复杂度,为了便于辨识,可以命名为main.py或者__main__.py。

相关项目的环境配置加载、资源初始化等,都应该放在入口文件中。

实际项目实践中,可能会添加一些辅助工具脚本,虽然本质上,也可以作为项目入口文件,但是,更多的是作为临时性使用的,比如数据初始化、异常数据修复等功能脚本等,命名应当尽量明确,与项目的启动入口文件能做明确区分。

3、文档和注释

应当为关键的函数、类、方法、模块编写docstring,尽量清晰描述其功能及用法。

应当在关键变量、关键逻辑处添加必要的注释,解释代码的意图及实现细节。

必须说明的是,虽然名为“最佳实践”,但是还是要结合具体的项目需求,如果一味机械地执行,导致开发过程中的束手束脚,反而得不偿失。

总结

本文介绍了模块中的几个关键内置变量,介绍了模块和入口文件的区别,以及入口文件的作用,最后给出了一些Python项目代码组织的最佳实践。

感谢您的拨冗阅读,如果对您学习Python有所帮助,欢迎点赞、关注。

78ea38ed00e7c21f0db9b6ceb8e0aeea.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南宫理的日知录

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

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

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

打赏作者

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

抵扣说明:

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

余额充值