Python导⼊模块时遇到的错误分析
当遇到⽆法导⼊某个python模块时,可能会是没有安装某个模块,也有可能是某模块在加载过程中失败,也有可能是陷⼊了循环导⼊的问题。本⽂详细解释了这个问题。
1. 模块未安装或者路径不对
ImportError: No mudule named myModule
有两种可能,⼀是该模块没有安装,⼀般可以⽤
pip install %module_name%
来解决。注意有时候模块安装包名并不等于要导⼊的模块名。这种情况下可以通过pip search | list命令来尝试到正确的包。
另⼀种情况就是包虽然安装了,但当前运⾏的程序加载的路径有错。python运⾏时将从以下位置尝试加载python modules:
* 当前⽬录
* 环境变量$PYTHONPATH所指⽰的值,这是⼀个由“:”分隔的字符串,各个⼦字符串都是⽂件系统的⼀个路径。
* 标准库⽬录,如dist-site-packages下的模块。
* 在.pth⽂件中指定的路径,如果存在.pth⽂件的话。
致美丽的你收视率
可以使⽤以下⽅式来查看python运⾏时的包含路径:
import sys
print(sys.path)
在运⾏出错的脚本装头部加上这⼀段代码,然后在控制台中查看打印出来的python类库路径,检查安装包是否已包含在上述路径中。
***可以通过下⾯的⽅式将未包含在路径中的模块临时包含进来:***
sys.path.append("path/to/module")
另外,还可以在shell窗⼝中查看当前的python包含路径:
echo $PYTHONPATH
2. ⽆法导⼊已存在的模块
如果要导⼊的模块包含了native代码,并且native代码加载(初始化)失败时,就会导致这种错误。使⽤ssl, gevent等涉及native的模块时,如果对应的native程序并未安装,则会出现这样的错误。
另⼀种错误情况是,使⽤相对路径导⼊时,⽗模块还未导⼊成功。见下⾯的代码:
main.py
mypackage/
__init__.py
mymodule.py
myothermodule.py
mymodule.py如下所⽰:
#!/usr/bin/env python3
# Exported function
def as_int(a):
return int(a)
# Test function for module
def _test():
assert as_int('1') == 1
if __name__ == '__main__':
_test()
以及myothermodule代码如下所⽰:
#!/usr/bin/env python3
from .mymodule import as_int
# Exported function
def add(a, b):
return as_int(a) + as_int(b)
# Test function for module
def _test():
assert add('1', '1') == 2关于初夏的诗句
if __name__ == '__main__':
_test()
如果执⾏mypackage/myothermodule,则会报以下错误:
Traceback (most recent call last):
File "myothermodule.py", line 3, in <module>
from .mymodule import as_int
SystemError: Parent module '' not loaded, cannot perform relative import
[这篇⽂章](#Relative imports in Python 3)给出了更详细的解答。
中国名酒
3. 循环导⼊
这种错误称之为"circular (or cyclic) imports"。是python独有的⼀种导⼊错误,在象java这样的语⾔中就不存在。
假设有如下两个⽂件,a.py和b.py:
#a.py
print "a in"
import sys
print "b imported: %s" % ("b" dules, )
import b
print "a out"
公磊八卦
print b.x
以及:
#b.py
print "b in"
import a
母婴用品品牌print "b out"
x = 3
执⾏python a.py,将得到以下结果:
$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
Traceback (most recent call last):
File "a.py", line 4, in <module>
import b
File "/home/shlomme/tmp/x/b.py", line 2, in <module>
import a
File "/home/shlomme/tmp/x/a.py", line 7, in <module>
print b.x
AttributeError: 'module' object has no attribute 'x'
出现这种情况的原因是产⽣了循环导⼊。循环导⼊,以及在导⼊过程中python进⾏了加锁操作,最终导致在模块b未导⼊完成时就引⽤了其中的名字。
黄瀞怡
判断导⼊错误是否是因为循环导⼊引起的,主要看堆栈中是否出现两次重复的导⼊。⽐如上述堆栈中a.py出现两次,因此可以判断是这个⽂件引起的循环导⼊。
要解决这个问题,可以把模块看成⼀种资源,对所有要引⼊的模块进⾏编号,再按静态资源排序法顺次导⼊,就可以避免循环导⼊。