内容提要
本文介绍Python代码复用与导入机制:通过pip安装现成包并用import调用;若代码未打包,需理解PYTHONPATH搜索路径。文章区分脚本与模块,说明`python -m`执行模块并保留包结构,讲解绝对引用与相对引用的用法,并推荐规范项目结构,将工具代码做成可安装库,便于notebook和脚本引用。
延伸解读
PYTHONPATH:import 背后的搜索机制
文章指出,import 能直接使用库名,是因为 Python 并非搜索整个硬盘,而是依赖 PYTHONPATH 环境变量。该变量是一个路径列表,Python 会依次在这些路径以及 site-packages 中查找库。如果下载的代码文件夹不在这些路径中,import 就会失败。理解这一点,就能明白为什么把代码放在当前目录下可以导入,换到其他位置却报错。
脚本与模块:__name__ 与 -m 参数的作用
文章区分了脚本和模块。直接运行 python somefile.py 时,该文件被当作主模块,其 __name__ 被设为 "__main__",Python 不会保留它在包中的真实名称,因此它难以通过相对引用找到同级或上下级模块。而使用 python -m sound.formats.wavwrite 执行时,Python 会保留包结构信息,使模块间的相对关系得以维持,便于内部引用。
绝对引用与相对引用的适用场景
文章说明,以 import sound 这类不带点号开头的写法是绝对引用,通常用于已安装的包。相对引用则以点号开头,一个点表示当前文件夹,两个点表示上一级文件夹,适合那些明确作为工具代码、属于更大结构且几乎不会作为主模块运行的模块。例如在 sound/effects/surround.py 中,可以用 from ..formats import wavwrite 引用上级包中的模块。
将工具代码打包为可安装库的实践建议
针对散落各处的分析代码难以互相引用的问题,文章推荐一种项目结构:将工具代码放在 projectname/projectname/ 下,包含 __init__.py、config.py、data.py、utils.py 等,并配合 setup.py。这样可以把工具代码做成可安装的库,然后在独立的 notebook 和 scripts 中像使用 numpy、pandas 一样引用。安装时在 projectname 目录下执行 pip install -e . 即可。
Q&A
Python 中如何通过 pip 安装并使用现成的包?
使用 pip install 包名 安装,然后通过 import 包名 或 from 包名 import 模块 等方式导入并使用其中的函数。
为什么下载了开源代码文件夹后直接 import 会报错?
因为 Python 不会搜索整个硬盘,而是根据 PYTHONPATH 环境变量中列出的路径来查找库。如果代码所在文件夹不在这些路径中,就会找不到模块而报错。
python -m 命令有什么作用?
python -m 用于以模块方式执行 Python 文件,它会保留包的结构信息,让 Python 知道模块之间的相对关系,从而正确执行模块中的代码。
绝对引用和相对引用有什么区别?
绝对引用以包名开头,如 import sound.formats.wavwrite;相对引用以点开头,如 from . import echo 或 from ..formats import wavwrite,其中 . 表示当前文件夹,.. 表示上一级文件夹。相对引用主要用于工具代码,这些代码通常不会作为主模块运行。
如何组织 Python 项目以便代码重用?
推荐将工具代码组织成一个可安装的库,包含 __init__.py、setup.py 等文件,然后通过 pip install -e . 安装,这样就能像使用 numpy、pandas 一样在 notebook 和脚本中引用。
脚本和模块在 Python 中有什么区别?
脚本是直接运行的 .py 文件,其 __name__ 属性为 '__main__';模块是被导入的 .py 文件,其 __name__ 为模块名。脚本通常作为程序入口,而模块提供功能供其他代码调用。