我们当前写的模块(.py文件)如果需要使用别人写好的代码,一般会使用from…import…来导入,以from A import B为例,我们从案例出发,谈谈A与B的几种可能的情况
故事大背景的文件结构如下图所示:
Case1: A是一个包(文件夹),B是一个模块(.py文件)
话说今日红太狼在家无聊,想给身边的人发发消息聊聊天,她首先打算找小白狼,于是红太狼在它的模块(红太狼.py)下写入了如下代码,并运行:
注:小白狼的语音信箱的代码是这样的
我们不难看出,红太狼写的代码中,“小白狼家”是一个包(文件夹),而 import 的小白狼语音信箱是一个模块(.py文件),在python中,万物皆为对象,这里导入的小白狼语音信箱就是一个对象,执行这个对象的呼叫小白狼方法,红太狼就联系到小白狼了
Case2: A是一个模块,B是一个函数方法
还是刚刚的背景话题,其实,红太狼还可以这样联系小白狼,”呼叫小白狼“是一个函数对象,函数是callable的,所以可以直接调用(关于callable的细节,欢迎阅读我主页下的另一篇blog)
Case3: 直接import 包
红太狼找小白狼聊完,又想起了美味的懒羊羊,于是她又去羊村找懒羊羊的模块,但是从目录结构中,她发现羊村目录并没有懒羊羊的模块(懒羊羊.py),红太狼灵机一动,执行了如下代码,成功找到了懒羊羊
原理是什么呢?刚刚说过,每一个包都有一个__init__.py文件,当我们 import 一个包,比如import 羊村,在红太狼的代码中,羊村就变成了一个对象,这个对象的所有属性与方法(函数)都定义在了 __init__.py 模块下,我们来看看这个模块
接下来是另一个话题:如何保证红太狼和羊村"永不失联"呢?
我们看另一个背景,刚刚,我们把狼堡,羊村,小白狼家等几个包作为一个项目打开,所以不同包之间可以项目访问,但是在实际情况下,我们需要借用的项目并不一定在我们的当前目录中,比如下图项目结构:
在这个项目结构中,红太狼就与小白狼"失联"了,那么如果我们想和某个项目联系起来,应该怎么办呢?
我们在安装python时,其安装目录下一定有一个Lib文件夹,Lib全称为Library,即专门存储库的文件夹,当我们 import A时,python不仅会检查当前项目中有没有A,还会去其安装目录下的Lib文件夹检查有没有A
如图,我们把羊村项目放进了Lib文件夹,那么即使在红太狼的当前项目中没有羊村这个项目,红太狼也可以直接引用这个项目
———————————————————————————————————————————
补充:sys.path
sys.path
是 Python 的一个列表,包含了解释器查找模块时所使用的路径。每当你在代码中使用 import
语句来导入模块时,Python 就会在 sys.path
列表中按照顺序查找指定的模块。
作用
sys.path
的主要作用是告诉 Python 解释器应该到哪些目录去查找模块和包。当你导入一个模块时,Python 会按照 sys.path
中的路径顺序逐一查找,直到找到指定的模块为止。如果在所有路径中都没有找到,解释器将会抛出 ModuleNotFoundError
异常。
组成部分
sys.path
列表中的路径通常包括以下几部分:
- 当前脚本的目录:即运行脚本所在的目录。如果运行的是一个模块而不是一个脚本,则可能是空字符串
''
,表示当前目录。 - PYTHONPATH 环境变量:如果设置了这个环境变量,它的值(一个或多个目录)会被添加到
sys.path
中。 - 标准库目录:Python 自带的标准库目录,比如
Lib
目录。 - 安装的第三方包目录:通过包管理工具(如
pip
)安装的第三方包所在的目录。
示例
以下是一个简单的示例,展示如何查看和修改 sys.path
:
import sys
# 打印当前的 sys.path
print("Original sys.path:")
for p in sys.path:
print(p)
# 假设你想添加一个新的目录到 sys.path 中
new_path = "/path/to/your/module"
if new_path not in sys.path:
sys.path.append(new_path)
# 打印修改后的 sys.path
print("\nModified sys.path:")
for p in sys.path:
print(p)
注意事项
- 顺序:
sys.path
中路径的顺序很重要,Python 会按照顺序查找模块。如果有多个同名模块,先找到的那个会被导入。 - 临时修改:临时修改
sys.path
是一种常见的做法,特别是在开发和测试过程中。但在生产环境中,最好将模块放在标准位置,以避免路径问题。