导入与系统模块同名的模块
我的情况和这个问题有点类似……不过有一点不同。
在我们的python/django项目中,有一个叫utils的文件夹,里面放着一些基本的函数……
有时候,我们需要通过控制台运行一些模块来测试,比如这样:
python myproject/some_module.py
一切都很好,直到python尝试从我们的 utils 文件夹中导入东西……
from utils.custom_modules import some_function
ImportError: No module named custom_modules
我检查了我的python路径,我们的项目在列表中,每个项目文件夹下都有__init__.py
文件,当我在项目目录下运行ipython时……一切正常,否则,python就会从它自己的utils文件夹中导入……
我的同事们用同样的方法没有任何问题,但在我的环境中却出现了ImportError
错误……我们大家都忽略了什么问题呢?
更新:我的项目目录和每个子目录都有__init__.py
文件,我可以毫无问题地从我的项目中导入其他模块……当我在不同于我的项目的文件夹中运行ipython时,导入没有问题……
from someothermodule.submodule imprort blahblahblah
但是,当涉及到导入utils时,就失败了……
更新2:问题的原因是django文件夹下的utils目录,它也在python路径中……
2 个回答
我就不啰嗦了,直接说吧,尽量不要把自己写的模块名字和标准库的模块名字搞混。
如果你想保持这个名字不变,那么在每个引用你自己工具模块的地方,都得用类似下面的写法:
import sys, imp
utils = sys.modules.get('utils')
if not utils: utils = imp.load_module('utils',*imp.find_module('utils/utils'))
不过,如果你改名字后需要修改的地方不多,我建议你还是改一下名字比较好。
请查看关于绝对导入和相对导入的PEP文档,里面有详细的解释。你可能想要这样做:
from .utils.custom_modules import some_function
如果你在一个包的顶层文件中。
补充说明:这只能在包内部进行。这是有原因的——如果你正在导入项目中的某个东西,那你实际上已经把它当作一个Python包来使用了,所以你应该真正把它做成一个包。你可以通过在项目目录中添加一个__init__.py
文件来实现。
补充说明2:你已经完全改变了问题的方向。虽然可能有办法绕过这个问题,但正确的做法是不要把你的包和内置包用同样的方式来引用。你要么需要重命名utils
,要么把它做成另一个包的子包,这样你就可以用一个不冲突的名字来引用它(比如from mydjangoapp.utils.custom_modules import some_function
)。