Python模块搜索路径问题
我正在尝试搭建一个开发环境,但发现 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 个回答
在/usr/lib/python2.6/site-packages里,foo到底在干嘛呢?
听起来你在本地目录里创建了foo,但你导入的可能不是那个。
试着把site-packages里的foo/bar删掉。
确保你的目录结构看起来像这样:
/foo/__init__.py
/bar/__init__.py
/commands.py
另外,最好不要把自己的模块命名为Python标准库里的名字——你能把你的commands.py改个名字吗?
你提到在当前目录下有一个 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
中的函数,这些函数可以根据路径为你定位模块,也可能会很有帮助。