python import用法总结


最近写代码的时候又遇到了Import出错的问题,以前遇到这类问题总是赶紧Google一下,尽快找到解决方案,最近又遇到了这个问题,小小的研究了一下,借这个机会稍微总结一下import的用法。

python import原理

要想用根本上解决这个问题,就必须了解import的工作原理。稍微Google了一些,在执行import时分如下几步进行:

  1. 创建一个新的、空的 module 对象(它可能包含多个 module);
  2. 将该 module 对象 插入 sys.modules 中;
  3. 装载 module 的代码(如果需要,需先编译);
  4. 执行新的 module 中对应的代码。

import会出错问题就在于第三步。首先会找到module所在的位置,其搜索顺序是:

sys.path -> PATHONPATH -> python默认路径。我们最主要使用的就是sys.path了。sys.path是一个list,是import的搜索路径, python程序运行时会自动将该入口程序的所在目录添加到sys.path的首位;然后就是python的第三方库的安装路径。如图所示:

因为这个机制,就产生了很多的问题。当程序比较大的时候,因此import只关心入口程序的path以及第三方库,所以在使用一些自定义的package时就会出现无法找到的错误。

import的几种不同的使用情况

同级目录 不在包内

项目结构如图所示:

这里file0.py和file01.py是在项目的根目录,也就是最简单的情况

代码分别如下:

# file0.py
a = 1

# file01.py
from file0 import a
print(a)

代码非常简单,两个文件在同级根目录下,运行成功。

同级目录下的包

结构如图:

代码如下:

# file0.py
from test1 import file1
file1.pr(1, 2)

# test1/file1.py
def pr(x, y):
    print(x+y)

这种情况是比较常用的情况,file0.py作为入口函数,调用其子目录的包里的module。代码运行成功

隔壁目录下的包文件

结构如图:

代码如下:

# test1/file1.py
def pr(x, y):
    print(x+y)

# test2/file2.py
from test1 import file1
file1.pr(1, 1)

运行代码发生错误:

分析一下原因,由于import是根据sys.path来搜索的,而sys.path添加的又是入口程序的目录,在当前目录下当然找不到同级文件夹了。在入口代码加上输出sys.path的代码,结果如下:

我们看到第一个路径就是当前入口程序的所在目录,与之前分析符合。

如何解决这个问题?既然知道了import的工作原理,最直接的想法就是把test1的路径加到sys.path里,但是不太好实现;退一步,我们只要把test2和test1的父目录加到sys.path里就可以了。修改代码:

# test1/file1.py
def pr(x, y):
    print(x+y)

# test2/file2.py
import sys
sys.path.append('..')
from test1 import file1
file1.pr(1, 1)

代码运行成功。

复杂情况

文件结构不变:

代码如下:

# test2/file2.py
import sys
sys.path.append('..')

from test1 import file1
file1.pr(1, 1)

# test1/file1.py
import file11
def pr(x, y):
    print(file11.add(x, y))

# test1/file11.py
def add(x, y):
    return x+y

运行代码,出现错误:

在这里上一个方法就行不通了,分析一下:

入口文件还是file2.py,因此sys.path里应该有test2文件夹,我们又手动加入了’..’,因此还包括了test2的父文件夹。因此,我们from test1 import file1成功了;接下来,在file1里,我们想要import同级module file11.py 。我们直接使用import file11,看起来是没有问题的,但是程序也就是在这里报了错。分析一下,因为我们是直接使用的import file11操作,也就是直接在sys.path中搜索file11,当然是搜索不到的。想要使用到file11,sys.path必须要包含test1路径。

找到了问题的所在,我们只要对症下药即可。我们再把test1的路径加入sys.path不就可以了。

代码如下:

# test1/file1.py
import sys, os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
print(BASE_DIR)
sys.path.append(BASE_DIR)

import file11
def pr(x, y):
    print(file11.add(x, y))

总结一下,就是在这个包的入口文件处,将这个包的目录加入到sys.path中即可。这里添加的是绝对路径,因此在其他位置调用该包也可以正常工作。

小结

基本上常见的情况就是这些了,其实对于这些问题,有一个更加简便的方法:使用pycharm pycharm在使用的时候,会自动把项目的根目录加到sys.path里,上述问题自动解决🤪(pycharm真相)所以说写项目的时候还是用pycharm吧!


2022.11.9更新

这个问题真是太常见了,总是遇到,干脆置顶吧


评论
 上一篇
并查集 并查集
最近看到一道这样的蓝桥杯题目: 问题描述   w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。   这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成
2020-03-04
下一篇 
动态规划解KMP算法 动态规划解KMP算法
动态规划解KMP算法KMP算法是一个非常经典的字符串匹配算法,效率很高,其原因也在于使用了动态规划的设计思想,但是着实复杂。。为了更加便于理解,本文采用的是一种二维dp数组的方式,而不是一般资料里非常神奇的一维数组(水平有限,菜),但是问题
2020-02-24
  目录