python import 搜索包路径的机制,以及添加自定义python包的方法

     阅读:52

系统:win10(linux系统也是类似的方法)
python:3.8.3

正文

python import 的搜索方法

在python中,有模块(module)和包(package)这两个概念。
一个.py文件就是一个模块;一个包含__init__.py文件的文件夹就是一个包,也就是模块的集合

python在import时,会从指定的路径中去搜索包。其中有一些是搜索路径的基准。
在终端中利用命令:python -c 'import site;print(site.getsitepackages())'来查看基准路径:

['C:\\Users\\username\\AppData\\Local\\Programs\\Python\\Python38', 
'C:\\Users\\username\\AppData\\Local\\Programs\\Python\\Python38\\lib\\site-packages']

然后,可以利用sys.path查看目前所有的搜索路径:

import sys
for path in sys.path:
	print(path)

我的输出如下:

d:\Computer_Programming\python\test
C:\Users\username\AppData\Local\Programs\Python\Python38\python38.zip
C:\Users\username\AppData\Local\Programs\Python\Python38\DLLs
C:\Users\username\AppData\Local\Programs\Python\Python38\lib
C:\Users\username\AppData\Local\Programs\Python\Python38
C:\Users\username\AppData\Roaming\Python\Python38\site-packages
C:\Users\username\AppData\Local\Programs\Python\Python38\lib\site-packages
......

可以看到,其中比基准路径多了很多其他的路径。
第一个是我们的当前路径,python会优先搜索我们当前路径下的包和模块。剩下的也都是python import时的搜索路径

注意

sys.path输出的路径的前后顺序就是python搜索包的前后顺序,这一点一定要注意。

比如,我们修改了python38路径下的一个名为mypackage的包文件夹,但是在python38\lib路径下也有一个同名的包,此时无论怎么修改python38路径下的那个包的内容,最后都影响不到import mypackage,因为python使用的一直都是python38\lib路径下的那个mypackage包


添加和使用自己写的python包

假设我们python包的结构为:

mypackage
--__init__.py
--submodule.py

关于__init__.py文件的使用,以及import … 和 from … import …的说明,见另一篇文章

我们自己写的python包所放的位置有多种选择:

方法一

把mypackage文件夹放在当前路径下,则在当前路径下的.py文件中可以直接:import mypackage。但是这种方法很不方便,如果在另一个路径下写.py文件的话,就得重新copy一份mypackage文件夹到另一路经下。

方法二(使用pth文件)

我们还可以把mypackage文件夹放在任意路径下,比如我放在:d:\Computer_Programming 下。
然后,我们就可以在上述的两个基准路径的其中一个下添加一个.pth文件,文件名任意。内容就是mypackage文件夹所在的路径,即 d:\Computer_Programming:
在这里插入图片描述

然后可以进行验证:

import mypackage
print(mypackage.__file__) # 查看mypackage包的路径
输出如下:
D:\Computer_Programming\mypackage\__init__.py

再用sys.path查看下搜索路径,就可以发现,输出中已经包含 d:\Computer_Programming 路径

方法三(不使用pth文件,常见)

我们还可以把mypackage文件夹放在上述sys.path输出的任一路径下。不过一般放在 ...\Python38\lib\site-packages 这个路径下,因为这个路径下存放的都是第三方包和模块,打开之后可以看到,很多我们安装的第三方包和模块都在这里;
而另一个常见的...\Python38\lib路径下存放的都是内置的包和模块。

所以,把mypackage文件夹放到 ...\Python38\lib\site-packages 路径下,之后不需要.pth文件,就可以直接使用:import mypackage
进行验证:

import mypackage
print(mypackage.__file__) # 查看mypackage包的路径
此时输出如下:
C:\Users\username\AppData\Local\Programs\Python\Python38\lib\site-packages\mypackage\__init__.py
附注

我在windows中,尝试了只将mypackage文件夹的快捷方式(类似于linux下的软链接,因为不想把整个文件夹都copy过去)放在基准路径下,其他一样,最后发现行不通,import mypackage就会报错:

Traceback (most recent call last):
  File "d:\Computer_Programming\python\test\test.py", line 3, in <module>
    import mypackage
ModuleNotFoundError: No module named 'mypackage'

在这里插入图片描述

但是linux系统中,只把创建的指向mypackage的软链接放在基准路径下的话,仍然可以正常使用mypackage包
在这里插入图片描述

参考

site的官方文档:https://docs.python.org/zh-cn/3/library/site.html