Python的import你用对了吗
写一个中大型项目, 往往需要在项目根路径下安排多层级的子目录和文件, 然后各文件之间通过import
来相互连接.
各 python 文件之间如何通过import
连接?
我们要遵从一个规范:
所有 python 文件都要以项目根目录为起始点来import
, 当然除了目录下的__init__.py
文件, 该文件一般是通过from . import module
来使本目录和本目录下的module
文件做关联.
import
其他相关规范也需要注意:
- 所有
import
尽量放在代码文件的头部位置 - 每行
import
只导入一个对象 - 当我们使用
from xxx import xxx
时,import
后面跟着的对象要是一个package
(包对应代码目录)或者module
(模块对应代码文件), 不要是一个类或者一个函数 - 标准模块、第三方模块、自定义模块要按这个先后顺序排列, 三类之间使用一个空行分隔.
比如项目根路径为:
/path/project
项目的组织结构:
|
|
项目文件内容:
main.py
|
|
module.py
|
|
package1/module.py
|
|
package1/sub_package/module.py
|
|
package1/sub_package/__init__.py
|
|
package1/__init__.py
|
|
package2/module.py
|
|
package2/__init__.py
|
|
运行项目入口文件
|
|
输出结果为:
|
|
以上正确运行的约束条件为:
- 运行项目的入口程序文件, 必须在项目的根路径下;
import
的对象必须从项目根路径为起始点;- 如果
import
的对象为目录(package
), 则在目录下必须有__init__.py
文件, 且该文件中通过from . import module
的形式引入该目录下相关模块, 这样才可以使用相关模块, 否则虽然import package
时不会报错, 但使用package
下面的模块时就会提示找不到相关模块; - 如果
import
的对象为目录.文件
(package.module)这种形式, 目录下可以没有__init__.py
文件; - 如果以
from 目录 import 文件
这种形式, 目录下也可以没有__init__.py
文件;
值得解释的一个问题:
上面的 python3 环境并没有将项目根目录加入到sys.path
中, sys.path
指的是import
时 python 的查找路径, 为什么子目录中的 python 文件从项目根路径为起始点import
不会报错?
解答:
首先我们知道sys.path
中存储的是import
时 python 查找库的搜索路径, 通过打印该变量内容, 我们可知, ''
空字符串是第一个路径, 这个空字符串代表的是当前 python 文件的所在目录, 不论是绝对路径执行还是相对路径执行, 这个值都是一样的, 都是当前 python 文件所在的目录.
然后再回答一下上面的问题, 因为我们是以项目根路径下的 python 文件作为项目的执行文件的, 该文件的import
相当于把其他当前目录或各级子目录中的各个 python 文件中的代码(包括import
代码)都加载到了当前文件中, 所以子目录文件中的import
也是从项目根路径下开始的, 当然不会报错.
当然了, 我们要是单独执行子目录中的 python 文件, 就会报找不到模块的错误了.
还有一个问题, 以上我们部署到生成环境当然没问题, 问题是在项目开发过程中, 我们肯定是需要单独执行子目录中的 python 文件的, 这个时候改怎么配置呢?
解答:
把项目根目录加入到sys.path
中, 可通过如下方式设置:
|
|
这样子目录 python 文件在当前目录下找不到对象时, 就会去项目根路径下去找了.