您的位置:

python中相对导入报错(python导包报错)

本文目录一览:

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运行时的包含路径:

?

12

import sysprint(sys.path)

在运行出错的脚本装头部加上这一段代码,然后在控制台中查看打印出来的python类库路径,检查安装包是否已包含在上述路径中。

***可以通过下面的方式将未包含在路径中的模块临时包含进来:***

sys.path.append("path/to/module")

另外,还可以在shell窗口中查看当前的python包含路径:

echo $PYTHONPATH

2. 无法导入已存在的模块

如果要导入的模块包含了native代码,并且native代码加载(初始化)失败时,就会导致这种错误。使用ssl,

gevent等涉及native的模块时,如果对应的native程序并未安装,则会出现这样的错误。

另一种错误情况是,使用相对路径导入时,父模块还未导入成功。见下面的代码:

?

12345

main.pymypackage/ __init__.pymymodule.pymyothermodule.py

mymodule.py如下所示:

?

123456789101112

#!/usr/bin/env python3 # Exported functiondef as_int(a): return int(a) # Test function for module def _test(): assert as_int('1') == 1 if __name__ == '__main__': _test()

以及myothermodule代码如下所示:

?

1234567891011121314

#!/usr/bin/env python3 from .mymodule import as_int # Exported functiondef 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:

?

1234567

#a.pyprint "a in"import sysprint "b imported: %s" % ("b" in sys.modules, )import bprint "a out"print b.x

以及:

?

12345

#b.pyprint "b in"import aprint "b out"x = 3

执行python a.py,将得到以下结果:

?

123456789101112131415

$ python a.pya in b imported: Falseb ina inb imported: Truea outTraceback (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 aFile "/home/shlomme/tmp/x/a.py", line 7, in module print b.xAttributeError: 'module' object has no attribute 'x'

出现这种情况的原因是产生了循环导入。循环导入,以及在导入过程中python进行了加锁操作,最终导致在模块b未导入完成时就引用了其中的名字。

判断导入错误是否是因为循环导入引起的,主要看堆栈中是否出现两次重复的导入。比如上述堆栈中a.py出现两次,因此可以判断是这个文件引起的循环导入。

要解决这个问题,可以把模块看成一种资源,对所有要引入的模块进行编号,再按静态资源排序法顺次导入,就可以避免循环导入。

python包相对导入的陷阱是?

包相对导入的陷阱:混合使用,相比于Python 2.X的隐式包相对导入,以及Python 2.X和3.X中的显式包相对导入点号语法,有些时候从 sys.path上一个路径出发的绝对包导入会是更推荐的选择。这一问题可能看上去难以理解,但是当你开始编写自己的包,可能就会变得更加重要了。 如前所述,Python 3.X的相对导入语法和默认绝对导入搜索规则,让包内导入变得显式从而使其更容易被注意和被维护,而且允许你在一些命名冲突的情况下显式地进行选择。然而,你也必须注意到该模型带来的下面两个结果:在Python 3.X和2.X中,包相对导入语句的使用会隐式地将一个文件与一个包目录的角色进行绑定,并禁止该文件通过其他方式被使用。在Python 3.X中,新的相对导入搜索规则改变意味着一个文件不能像在2.X中那样同时扮演脚本和包模块的角色。这些约束的理由有些微妙,不过由于下面的两条同时成立:Python 3.X和2.X不允许随意使用from .的相对导入语法,除非发起导入的文件本身作为包的一部分(即该文件在其他地方被导入)。Python 3.X的导入不会搜索一个包模块自身的路径,除非使用了from .的相对导入语法(或该模块位于当前工作路径、顶层脚本的主目录下)。使用相对导入会阻止你在2.X和3.X中创建同时扮演可执行程序和外部可导入包角色的目录项。此外,一些文件在3.X中不能像在2.X中那样同时扮演脚本和包模块的角色。就导人语句来说,这些规则可以归结为下面的两行代码的形式:前一行在Python 2.X和3.X中都只用于包模式,而后一行在3.X中只用于程序模式。

最终的效果是不论2.X还是3.X中的文件,你都应该只选择一种使用模式,即包模式(使用相对导入)或程序模式(使用简单导入),并将真正的包模块文件单独放到一个子目录中,与顶层脚本文件隔离开来。

另一方面,你可以尝试手动改变sys.path(通常是一项脆弱并易出错的任务)或总是通过绝对导入使用完整的包路径,并且假定包的根目录位于模块搜索路径上,来替代包相对导入语法或简单导入。

Python 导入自建包报错ModuleNotFoundError: No module named xxx

如图,三个模块的关系:模块A导入模块B,而模块B导入模块C

执行模块A时,会报错ModuleNotFoundError: No module named xxx,说找不到模块C。

于是就打开模块B查看,发现导入模块C是正常的,这就让人很头疼

模块B和模块C是同一个包,而模块A又是在另一个包。同个包内的模块B可以用相对路径找到模块C,不同包的模块A则不能。

方案一:项目根目录为起始路径导入包

在IDE中执行python程序,编译器会自动把当前项目的根目录加入到包查找路径中,可以理解为加到PYTHONPATH下,所以导入写法如下:

方案二:导包时,把目标模块的路径加入包查找路径中

推荐使用方案一,养成好习惯,从项目根目录开始导包。

python导入py文件报错怎么办

其实这两个错误的原因归根结底是一样的:在涉及到相对导入时,package所对应的文件夹必须正确的被python解释器视作package,而不是普通文件夹。否则由于不被视作package,无法利用package之间的嵌套关系实现python中包的相对导入。

文件夹被python解释器视作package需要满足两个条件:

1、文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件。

2、不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。

补充:在"from YY import XX"这样的代码中,无论是XX还是YY,只要被python解释器视作package,就会首先调用该package的__init__.py文件。如果都是package,则调用顺序是YY,XX。

另外,练习中“from . import XXX”和“from .. import XXX”中的'.'和'..',可以等同于linux里的shell中'.'和'..'的作用,表示当前工作目录的package和上一级的package。