探寻Python导包路径机制

简介: 为什么我们`import os, improt sys, improt math`等模块,就可以成功导入其模块,而随便`import aaa`,就不行呢。那是因为`Python`的导包路径原因,让我们来康康`Python`的导包路径,是怎样的机制。

引言

为什么我们 import os, improt sys, improt math等模块,就可以成功导入其模块,而随便 import aaa,就不行呢。那是因为 Python的导包路径原因,让我们来康康 Python的导包路径,是怎样的机制。

<br/>

查看导包路径

可以通过内置sys模块来查看导包路径。

In [1]: import sys

In [2]: sys.path
Out[2]:
['D:\\Hui\\DevelopEnv\\Python\\Python379\\Scripts\\ipython.exe',
 'd:\\hui\\developenv\\python\\python379\\python37.zip',
 'd:\\hui\\developenv\\python\\python379\\DLLs',
 'd:\\hui\\developenv\\python\\python379\\lib',
 'd:\\hui\\developenv\\python\\python379',
 '',
 'd:\\hui\\developenv\\python\\python379\\lib\\site-packages',
 'd:\\hui\\developenv\\python\\python379\\lib\\site-packages\\IPython\\extensions',
 'C:\\Users\\Administrator\\.ipython']

In [3]:

<br/>

sys.path返回的是一个路径列表,其代表Python导包时搜素的路径

  • Python解释器sys.path里依次查找要导入的模块文件或包
  • '' 表示当前路径
  • sys.path列表中的路径的先后顺序代表了Python解释器在搜索模块时的先后顺序

<br/>

内置模块、包存放路径

os, sys, json等一些内置模块、包都存放在你下载 Python解释器时,其保存路径的 Lib目录

<br/>

存放路径以我个人的举例:

D:\Hui\DevelopEnv\Python\Python379\Lib

<br/>

Python内置模块、包的存放目录1

<br/>

Python内置模块、包的存放目录

<br/>

下载的第三方库存放路径

requestsipython这些自己下载的第三方库等都存放在 Lib下的 site-packages目录下

<br/>

存放路径以我个人举例

D:\Hui\DevelopEnv\Python\Python379\Lib\site-packages

<br/>

Python下载的第三方库存放位置

<br/>

然而导包路径sys.path就包含这两个路径

sys.path导包路径

<br/>

因此我们使用import osimport sysimport jsonimport requests等都可以找到相应的模块和包

<br/>

如果导入模块和包时在sys.path中没有搜索到相对应的模块,则会报如下错误

ModuleNotFoundError: No module named 'xxx'

<br/>

import aaa
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-4-37ad1770aa41> in <module>
----> 1 import aaa

ModuleNotFoundError: No module named 'aaa'

其原理跟我们的电脑的环境变量-Path有点像。

我们可以在cmd窗口输入python可以打开python 交互解释器pip install xxx可以下载第三方库。都是因为系统环境变量-Path,有具体可执行文件的路径

系统环境变量Path

<br/>

python

<br/>

可执行的脚本

<br/>

追加新的导包路径

我们可以在程序运行时动态追加新的导包路径,代码如下
sys.path.append('D:\Hui\Code\Python\demo')        # 追加到末尾

sys.path.insert(0, 'D:\Hui\Code\Python\demo')   # 追加到开头位置,可以确保先搜索这个路径

<br/>

ipython 测验

追加导包路径到末尾

<br/>

追加导包路径至开头

<br/>

现在D:\Hui\Code\Python\demo目录下有一个aaa.py模块。

测试动态追加导包路径

<br/>

aaa.py模块内容如下

# aaa.py

def test():
    print('追加导包路径成功')

导包路径没追加D:\Hui\Code\Python\demo时,import aaa会报错

追加之后,在试试

追加导包路径测试结果

<br/>

追加导包路径之后就可以成功导入并使用了。

<br/>

Django项目追加导包路径

来康康导包路径的具体应用场景。

Django中我们通常把子应用模块统一放在apps包下,但在注册子应用的时候,该如何设置路径呢?

Django Apps

<br/>

我们在配置文件settings.pyordevelop.py中添加打印导包路径的代码

import sys
from pprint import pprint

pprint(sys.path)

其中pprintpretty print美化输出的意思,这样输出的列表不会在一行上。

然后运行Django程序查看导包路径结果

['C:\\Users\\Administrator\\Desktop\\meiduo_project\\meiduo_mall',
 'C:\\Users\\Administrator\\Desktop\\meiduo_project',
 'D:\\Hui\\DevelopTools\\PyCharm '
 '2020.2.3\\plugins\\python\\helpers\\pycharm_display',
 'd:\\hui\\developenv\\python\\python379\\python37.zip',
 'd:\\hui\\developenv\\python\\python379\\DLLs',
 'd:\\hui\\developenv\\python\\python379\\lib',
 'd:\\hui\\developenv\\python\\python379',
 'D:\\Hui\\VirtualEnv\\meiduo_mall',
 'D:\\Hui\\VirtualEnv\\meiduo_mall\\lib\\site-packages',
 'D:\\Hui\\DevelopTools\\PyCharm '
 '2020.2.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend']

已知导包路径

  • meiduo_project/meiduo_mall

已知users应用所在目录

  • meiduo_project/meiduo_mall/meiduo_mall/apps/users

因此导入users 应用的路径可以写为:meiduo_mall/apps/users

知道导包路径我们就好在配置文件settings.pyordevelop.py中注册子应用

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'meiduo_mall.apps.users',    # 注册用户模块
]

<br/>

是否可以将注册users应用做的更加简便?按照如下形式,直接以应用名users注册

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'users',    # 注册用户模块
]

<br/>

分析:

  • 已知导包路径

    • meiduo_project/meiduo_mall
  • 已知users应用所在目录

    • meiduo_project/meiduo_mall/meiduo_mall/apps/users
  • 若要直接以应用名users注册

    • 需要一个导包路径:meiduo_project/meiduo_mall/meiduo_mall/apps

解决办法

  • 追加导包路径:meiduo_project/meiduo_mall/meiduo_mall/apps

<br/>

在配置文件settings.pyordevelop.py中追加导包路径

sys.path.insert(0, r'meiduo_project/meiduo_mall/meiduo_mall/apps/users')

Django项目追加导包路径

<br/>

在项目中一般不会写死路径,因此利用BASE_DIR来动态拼接路径

打印BASE_DIR内容如下

'C:\\Users\\Administrator\\Desktop\\meiduo_project\\meiduo_mall\\meiduo_mall'

其路径怎么得来的呢,我们来分析一下代码

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  • 其中__file__是指向当前模块
  • os.path.abspath(__file__)是获取当前模块的绝对路径
  • os.path.dirname(os.path.abspath(__file__))则是根据当前模块路径获取其所在目录

因此:

os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

就是获取当前模块的所在目录的上一层目录。

Django项目BASE_DIR

<br/>

我这里的当前模块是develop.py,所在目录为settingssettings的上一层目录则是meiduo_mall

因此我们可以通过BASE_DIR动态拼接路径,来添加导包路径

# 追加子应用导包路径
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

注册子应用直接写应用名就可以了。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 'meiduo_mall.apps.users'

    'users'
]

<br/>

导包路径的作用

通过查看导包路径,可以快速的知道项目中各个包该如何的导入。

接手项目时,可以尽快的适应项目导包的方式。

通过追加导包路径,可以简化某些目录复杂的导包方式。

<br/>

重新导入模块

模块被导入后,import module不能重新导入模块,重新导入需用imp下的reload

from imp import reload

<br/>

我们还是已上文提到的aaa.py模块举例

# aaa.py

def test():
    print('追加导包路径成功')

<br/>

ipython 测验

In [21]: import aaa

In [22]: aaa.test()
追加导包路径成功

In [23]:

这时不要关掉ipython然后修改aaa.py模块的如下

# aaa.py

def test():
    print('重新导入模块测试')

<br/>

然后回到ipython中测验

# 没修改前
In [21]: import aaa

In [22]: aaa.test()
追加导包路径成功

# 修改之后
In [23]: aaa.test()
追加导包路径成功

In [24]: import aaa

In [25]: aaa.test()
追加导包路径成功

In [26]:

其实aaa.py已经修改了,只是当前ipython交互器不知道,我们可以再开一个ipython交互器验证一下

In [3]: import sys

# 我的aaa.py 模块不在当前导包路径下,因此要动态追加一下
In [4]: sys.path.insert(0, 'D:\Hui\Code\Python\demo')

In [5]: import aaa

In [6]: aaa.test()
重新导入模块测试

In [7]:

<br/>

因此aaa模块被导入后,import aaa不能重新导入模块,重新导入需使用如下方式

# 没修改前
In [21]: import aaa

In [22]: aaa.test()
追加导包路径成功

# 修改之后
In [23]: aaa.test()
追加导包路径成功

In [24]: import aaa

In [25]: aaa.test()
追加导包路径成功

In [27]: from imp import reload

In [28]: reload(aaa)
Out[28]: <module 'aaa' from 'D:\\Hui\\Code\\Python\\demo\\aaa.py'>

In [29]: aaa.test()
重新导入模块测试

<br/>

✍ 码字不易,万水千山总是情,点赞再走行不行,还望各位大侠多多支持❤️

<br/>

公众号

新建文件夹X

大自然用数百亿年创造出我们现实世界,而程序员用几百年创造出一个完全不同的虚拟世界。我们用键盘敲出一砖一瓦,用大脑构建一切。人们把1000视为权威,我们反其道行之,捍卫1024的地位。我们不是键盘侠,我们只是平凡世界中不凡的缔造者 。
相关文章
|
10月前
|
存储 人工智能 运维
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
558 48
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
|
3月前
|
数据处理 开发工具 开发者
requirement.txt 管理python包依赖
在 Python 项目中,`requirements.txt` 用于记录依赖库及其版本,便于环境复现。本文介绍了多种生成该文件的方法:基础方法使用 `pip freeze`,进阶方法使用 `pipreqs`,专业方法使用 `poetry` 或 `pipenv`,以及手动维护方式。每种方法适用不同场景,涵盖从简单导出到复杂依赖管理,并提供常见问题的解决方案,帮助开发者高效生成精准的依赖列表,确保项目环境一致性。
1099 4
|
开发者 Python
如何在Python中管理模块和包的依赖关系?
在实际开发中,通常会结合多种方法来管理模块和包的依赖关系,以确保项目的顺利进行和可维护性。同时,要及时更新和解决依赖冲突等问题,以保证代码的稳定性和可靠性
365 62
|
4月前
|
人工智能 测试技术 编译器
从 Python 演进探寻 AI 与云对编程语言的推动
Python 自 2008 年发布 3.0 版本以来,经历了持续演进与革新。十六年间,从 Python 3.0 到即将发布的 3.14,语言设计、性能优化、类库生态及虚拟机技术等方面均有显著提升。字符串处理、异步编程、类型系统等核心功能不断现代化,Faster CPython 和 JIT 编译技术推动运行效率飞跃。同时,AI、云计算等新兴技术成为其发展的重要驱动力。本文全面回顾了 Python 的演进历程,并展望未来发展方向。
177 2
|
10月前
|
人工智能 Python
【02】做一个精美的打飞机小游戏,python开发小游戏-鹰击长空—优雅草央千澈-持续更新-分享源代码和游戏包供游玩-记录完整开发过程-用做好的素材来完善鹰击长空1.0.1版本
【02】做一个精美的打飞机小游戏,python开发小游戏-鹰击长空—优雅草央千澈-持续更新-分享源代码和游戏包供游玩-记录完整开发过程-用做好的素材来完善鹰击长空1.0.1版本
422 7
|
5月前
|
测试技术 Python
Python测试报告生成:整合错误截图,重复用例执行策略,调整测试顺序及多断言机制。
如何组织这一切呢?你可以写一本名为“Python测试之道”的动作指南手册,或者创建一个包含测试策略、测试顺序、多断言机制的脚本库。只要你的测试剧本编写得足够独到,你的框架就会像一位执行任务的超级英雄,将任何潜伏于代码深处的错误无情地揪出来展现在光天化日之下。这些整理好的测试结果,不仅有利于团队协作,更像冒险故事中的精彩篇章,带给读者无尽的探索乐趣和深刻的思考。
149 10
|
数据采集 Python
Python实用记录(七):通过retinaface对CASIA-WebFace人脸数据集进行清洗,并把错误图路径放入txt文档
使用RetinaFace模型对CASIA-WebFace人脸数据集进行清洗,并将无法检测到人脸的图片路径记录到txt文档中。
308 1
|
10月前
|
测试技术 Python
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
490 31
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
|
10月前
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
770 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
Python
Python的模块和包
总之,模块和包是 Python 编程中非常重要的概念,掌握它们可以帮助我们更好地组织和管理代码,提高开发效率和代码质量
257 61

推荐镜像

更多