扩展Python搜索路径到其他源

147 投票
7 回答
317749 浏览
提问于 2025-04-16 00:35

我刚加入一个项目,这个项目的代码量挺大的。我们在Linux系统上开发,不使用集成开发环境(IDE),而是通过命令行来运行程序。我现在想弄明白,如何让Python在运行项目模块时找到正确的路径。比如,当我运行类似下面的代码时:

python someprojectfile.py

我得到的结果是:

ImportError: no module named core.'somemodule'

我在所有的导入中都遇到这个问题,所以我猜这可能是路径设置的问题。

我该如何让Python在导入文件时,搜索~/codez/project/以及里面的所有文件和文件夹,找到*.py文件呢?

7 个回答

9

我知道这个话题有点老了,但我花了一些时间才搞明白,所以想分享一下我的经验。

在我的项目中,我把主要的脚本放在一个父目录下,为了区分不同的模块,我把所有的辅助模块放在一个叫“modules”的子文件夹里。在我的主脚本中,我是这样导入这些模块的(以一个叫report.py的模块为例):

from modules.report import report, reportError

当我运行主脚本时,这样是可以正常工作的。不过,我想在每个模块里加一个main()函数,然后直接调用它们,像这样:

python modules/report.py

结果Python就报错了,说找不到“modules”这个模块。这里的关键是,默认情况下,Python会把脚本所在的文件夹加入到搜索路径中,但不会把当前工作目录(CWD)加入。所以这个错误其实是在说“我找不到modules这个子文件夹”。这是因为在report.py模块所在的目录下并没有“modules”这个子目录。

我发现最简单的解决办法是在Python的搜索路径中加入当前工作目录,只需要在文件的开头加上这一行:

import sys

sys.path.append(".")

这样一来,Python就会搜索当前目录,找到“modules”这个子文件夹,一切就正常了。

17

你还可以在这里了解一下Python包的相关内容:http://docs.python.org/tutorial/modules.html

根据你的例子,我猜你的包实际上是在~/codez/project这个地方。Python目录中的__init__.py文件可以把一个目录映射到一个命名空间。如果你的子目录里都有__init__.py文件,那么你只需要把基础目录添加到你的PYTHONPATH中。例如:

PYTHONPATH=$PYTHONPATH:$HOME/adaifotis/project

除了测试你的PYTHONPATH环境变量,正如David所解释的,你还可以在Python中这样测试:

$ python
>>> import project                      # should work if PYTHONPATH set
>>> import sys
>>> for line in sys.path: print line    # print current python path

...

243

有几种方法可以做到这一点:

  • 设置一个叫 PYTHONPATH 的环境变量,里面放上用冒号分隔的目录列表,这样 Python 就会在这些目录中查找你要导入的模块。
  • 在你的程序里,可以用 sys.path.append('/path/to/search') 来添加你希望 Python 查找模块的目录名。sys.path 就是 Python 每次被要求导入模块时会查找的目录列表,你可以根据需要修改它(不过我不建议删除任何标准目录!)。你在 PYTHONPATH 环境变量中放的任何目录,Python 启动时都会被加入到 sys.path 中。
  • 使用 site.addsitedir 来把一个目录添加到 sys.path。这个方法和直接添加的不同之处在于,使用 addsitedir 时,它还会在这个目录中查找 .pth 文件,并根据文件的内容可能会额外添加更多的目录到 sys.path。想了解更多细节可以查看文档。

你选择哪种方法取决于你的具体情况。记住,当你把项目分发给其他用户时,他们通常会以一种方式安装项目,使得 Python 的导入器能自动检测到 Python 代码文件(也就是说,包通常会安装在 site-packages 目录下),所以如果你在代码中修改 sys.path,可能就没必要了,甚至在其他电脑上运行时可能会产生不好的效果。对于开发来说,我猜设置 PYTHONPATH 通常是最好的选择。

不过,当你使用的东西只是运行在你自己的电脑上(或者你有一些非标准的设置,比如在某些网络应用框架中),做一些类似的事情也是很常见的:

import sys
from os.path import dirname
sys.path.append(dirname(__file__))

撰写回答