Python模块搜索路径问题

3 投票
2 回答
5302 浏览
提问于 2025-04-15 14:50

我正在尝试搭建一个开发环境,但发现 Python 似乎在使用 site-packages 目录里的模块。我希望它能使用我开发目录里的模块。

sys.path 返回了一堆目录,像这样:

['', '/usr/lib/python26.zip', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/lib/python2.6/site-packages' etc

这很好,它把当前目录作为查找的第一位置(至少我是这么理解的)。

好吧,现在如果我在当前目录创建一个叫 command.py 的文件,事情就会按我预期的那样工作。

>>> import commands
>>> commands.__file__
   'commands.pyc'

然后我退出 Python 解释器,再启动一个新的。我接着这样做:

>>> import foo.bar.commands

现在,我期待它从当前目录下的 ./foo/bar/ 去获取那里的 commands 模块。但实际上我得到的是这个:

>>> foo.bar.commands.__file__
    '/usr/lib/python2.6/site-packages/foo/bar/commands.pyc'

尽管在我的当前目录下确实有一个 ./foo/bar/commands.py。

使用 imp.find_module() 和 imp.load_module() 我可以正确加载本地模块。实际上有趣的是(虽然我不太明白这是什么意思)在这个序列中打印出的最后一行:

>>> import foo.bar.commands
>>> foo.bar.commands.__file__
   '/usr/lib/python2.6/site-packages/foo/bar/commands.pyc'
>>> foo.bar.__file__
   '/usr/lib/python2.6/site-packages/foo/bar/__int__.pyc'
>>> foo.__file__
    './foo/__init__.pyc'

所以如果它能在本地目录找到 foo/init.pyc,为什么就找不到本地目录里的其他文件呢?

谢谢!

2 个回答

0

在/usr/lib/python2.6/site-packages里,foo到底在干嘛呢?

听起来你在本地目录里创建了foo,但你导入的可能不是那个。

试着把site-packages里的foo/bar删掉。

确保你的目录结构看起来像这样:

/foo/__init__.py  
    /bar/__init__.py
        /commands.py

另外,最好不要把自己的模块命名为Python标准库里的名字——你能把你的commands.py改个名字吗?

3

你提到在当前目录下有一个 foo 文件夹,但你没有告诉我们 foo/__init__.py 文件是否存在(即使是空的也可以):如果这个文件不存在,Python 就会认为 foo 不是一个包。同样的道理适用于 foo/bar/__init__.py —— 如果这个文件不存在,即使 foo/__init__.py 存在,foo.bar 也不是一个包。

你可以通过放置 .pth 文件或者在你的包中明确设置 __path__ 来进行一些尝试,但基本的简单规则是:在你希望 Python 识别为包的每个目录中放一个 __init__.py 文件。这个文件的内容就是包的“主体”,所以如果你 import foo 并且 foo 是一个包含 foo/__init__.py 文件的目录,那么你导入的就是这个文件(无论如何,包的主体会在你第一次从这个包或其子包中导入任何东西时执行)。

如果这不是问题,看起来可能是其他的导入(或者明确的 sys.path 操作)搞混了你。用 -v 参数运行 Python 可以让导入过程变得非常清晰,这样会有帮助。另一个好的方法是在你认为有问题的导入之前放一个

import pdb; pdb.set_trace()

并在那时检查 sys.path、sys.modules(还有可能是其他一些高级结构,比如导入钩子)—— 比如,sys.modules['foo'] 是否已经定义?互动地尝试标准库模块 imp 中的函数,这些函数可以根据路径为你定位模块,也可能会很有帮助。

撰写回答