Python模块导入

前言

Python是一门非常灵活的语言,代码组织可以从一个文件到一个目录,再到包含很多目录很多文件的工程。
当代码量越来越大的时候,要思考如何将代码模块化,如何能更加优雅的组织文件。

概念

Python中有模块的概念,对应的就是一个py文件;包的概念对应的就是一个目录,在Python2中,
包中必须存在__init__.py文件,在Python3中这个规定已经不存在了,一个目录就是一个包。

导入

导入分为相对导入和绝对导入,在相对导入中又分为隐式导入和显示导入,隐式导入在Python3中已经废弃了,相对导入和绝对导入都是以包的概念来说的

隐式导入

没有指明从哪里导入的,例如标准库和第三方库可以直接导入,我们自己的文件也可以这样,但会带来一些歧义
假如存在这样一个目录

d1
 │ main.py
 └─d2
    │ p1.py
    │ p2.py
    │ __init__.py

# main.py
import d2.p2

# p1.py
def hello():
    print("hello")

# p2.py
import p1
p1.hello()

在d1文件夹下,运行main.py文件,python2是没有问题的,python3会报错,因为这种导入方式已经不支持了

如果在p2.py文件加上from __future__ import absolute_import,
同样也是会报错的

相对导入

from .xxx import yyy
.代表当前文件所在的目录
..代表当前文件的上一级目录或上一级目录的同级目录
...以此类推

from . import yyy
# 可以是从__init__.py文件中导入

绝对导入

from a.b.c import yyy
与相对导入不同的是绝对导入,标明了导入的文件的路径

如何用

Python提供了这两种导入方式,应该如何去组织代码。
官方推荐的是使用绝对导入,这样看着很清晰,Pycharm也提供了强大的重命名功能,一旦我们改变文件名或者目录名,import语句都会发生改变
我目前的方法是,在一个固定的,提供接口的模块内部使用相对导入,在外部的gui或者command接口文件使用绝对导入

绝对导入的路径应该怎么写?
在github上下载了几个项目,基本上是以下结构

project
  | main.py
  ├─mod1
  └─mod2

manage.py或者main.py在最外层,然后在main.py中导入模块

from mod1.package1 import xxx
from mod2.package2 import yyy

在运行的时候直接可以

python main.py 参数

入口文件main.py所在的文件夹会添加到sys.path的第一项,所以可以寻找到mod1和mod2包
以这种方式启动,入口文件中不能包含相对导入

如有错误,请大佬指正!

参考

https://ke.sifou.com/course/1650000037773462
https://segmentfault.com/a/1190000018032094

posted @ 2021-03-15 20:18  Makerdd  阅读(82)  评论(0)    收藏  举报