使用Python编写项目,经常会自定义一些模块文件(函数,类等),组织在不同的文件夹中,在其它Python文件中使用import语句导入使用。Python软件包和普通的文件夹不同之处在于有一个特定文件“__init__.py”。当导入该软件包中的模块时,Python解释器会首先执行该软件包的“__init__.py”文件。
将一个文件夹用作Python软件包时,该文件夹必须满足以下条件:
(1)文件夹中必须包含一个名为“__init__.py”的文件,该文件可以为空,但必须存在。它告诉Python该文件夹是一个可导入的模块或包。
(2)文件夹可以包含其他Python模块、子文件夹和“__init__.py”文件。这些文件和文件夹可以包含Python代码、函数、类等。
(3)软件包可以有自己的“__init__.py”文件,该文件通常用于初始化软件包或在导入软件包时执行某些操作。
“__init__.py ”文件在Python中被用来标识一个目录是一个Python包。其意义是:这个文件在以下几种情况下会被自动执行:
(1)导入包:当你导入一个包的时候,Python会首先执行该包的 “__init__.py” 文件。这使得你可以在 “__init__.py”文件中定义包级别的变量,或者执行一些初始化代码。
(2)包的初始化:当Python解释器启动时,它会查找所有的包,并执行每个包的 “__init__.py”文件。这使得你可以在包的级别上执行一些初始化代码,例如设置环境变量或加载配置文件。
(3)包内直接引用:如果在包的某个模块中需要引用包级别的变量或函数,那么Python会在加载该模块时执行 “__init__.py”文件。
值得注意的是,虽然可以在 “__init__.py” 文件中执行任意Python代码,但是有一些最佳实践和建议:
(1)不要执行非初始化代码:将 “__init__.py” 文件用于包的初始化,避免在其中执行可能会阻止包正常导入的代码。
(2)使用相对导入:如果你需要在 “__init__.py” 文件中导入包内的其他模块,请使用相对导入,以避免可能的循环导入问题。
(3)谨慎使用全局变量:在 “__init__.py” 文件中定义的变量是包级别的,可能会影响到包内的其他模块。因此,应该谨慎使用全局变量。
(4)“__init__.py”文件中的代码仅在导入该软件包时执行一次。如果需要在每次导入该软件包时都执行一些代码,可以在该模块中使用一个启动函数或者钩子,这样当该模块被导入时,该函数或钩子将被调用。
将自定义模块放在一个文件夹中作为软件包的好处是,可以将相关的Python代码组织在一起,方便管理和维护。此外,软件包可以包含多个模块,并且可以通过包管理工具(如pip)进行安装和分发。这对于第三方库和开源项目特别有用,因为它们可以被其他人轻松地安装和使用。
另外:
Python在启动时会执行所有的“__init__.py”文件来初始化包,这是为了设置环境变量或加载配置文件等。但是,当你在代码中导入某个软件包时,该软件包中的“__init__.py”文件会被再次执行。这是因为“__init__.py”文件中的代码是为包的导入而编写的,它定义了包的结构和行为。
例如,“__init__.py”文件可以定义模块的公开接口、设置模块的属性或状态,或者进行其他与模块相关的初始化操作。当模块被导入时,这些初始化操作是必要的,因此“__init__.py`文件会被再次执行。
需要注意的是,“__init__.py”文件中的代码只会在包首次被导入时执行一次。如果在之后的代码中再次导入同一个包,“__init__.py”文件将不会被重新执行。这样可以确保包的初始化操作只执行一次,避免重复执行初始化代码或导致意外的副作用。