python3的package、module到底该如何导入

  本文内容是对包和模块使用中各种奇怪错误产生原因的分析,对包和模块基本概念和用法有疑惑的请看文档【2】

问题     

最近把一个python2的老项目重构为python3,运行的时候报错:

ImportError: attempted relative import with no known parent package

        看了下是相对路径导入模块时出错,找了一圈资料,程序倒是跑起来了,不过有一个问题还是没有得到答案:对于结构复杂的项目,怎么导入模块才能既要用起来方便,又要迁移的时候不受影响?

看过的有效的文章有:

  1. 【1】python官方文档的Modules说明
  2. 【2】菜鸟教程翻译的官方文档Modules说明
  3. 【3】[译][python]ImportError:attempted relative import with no known parent package
  4. 【4】彻底明白Python package和模块
  5. 【5】关于python的pakage和module __all__ __path__的介绍

只能说,众说纷纭,反而更加迷糊了。自己按照文章【4】的思路,下载了文中列出的官方sound包,摸索了一会,发现点门道。这里偷懒只说结论,不上过程。

结论

以下内容每个目录下都已经有了空的__init__.py文件。

1.相对路径

(所有以 . 开头的)导入的时候,总是以import语句自己所在的模块路径为基准去寻找目标包或者模块:

from . import echo
from .. import formats
from ..filters import equalizer
import .sound.effects.echo
from .sound.effects import *


2.绝对路径


(所有不以 . 开头的)导入的时候,总是以主程序入口所在的路径(工作路径)为基准去寻找目标包或者模块,而与import语句自己所在的模块路径无关:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

 进一步地,所有相对路径能导入成功的都是:执行到import语句时,以import语句自己所在的模块的__package__值为基准去寻找目标包或者模块。

__file__=***\sound\effects\echo.py | __name__=sound.effects.echo   | __package__=sound.effects 

而主程序的__package__为空,自然不能用任何相对导入方式

__file__=***/pya.py | __name__=__main__             | __package__=None

现在再来看文章【3】给出的两种办法,其实都是想办法指定了__package__值,从而使相对导入成功的。但是这两种方法都太麻烦,局限性太大,我们就没有其他办法吗?

当然有!凡是这种以 from * import 方式,以及 * . * 方式导入的,被导入模块都有__package__,该模块的import都可以用相对路径。

import sound.effects
from sound.effects import *

 

总结:

  1. 主程序只能用绝对路径导入(不需要完整路径)。
  2. 导入时指定了包结构的模块,该模块导入其他模块时都可以用相对路径。
  3. 你还可以在每一个import之前,把要导入的包的相对路径转化为绝对路径(完整路径),然后再加入 sys.path,这样优点是可以直接用模块名,省去了一长串...加包名,缺点是每个有import的模块都需要这么做。这篇文章就是这么做的https://www.cnblogs.com/yinzhengjie/p/8587656.html

用如下执行方式试了,运行的很好啊。足以保证迁移也不会出问题了。

python ..\..\pya.py

最后

如果pya.py导入了

# import effects.echo
from sound.effects import echo

echo.py又导入

from ..filters import karaoke

那么karaoke.py还能再导入吗?

from ..effects import reverse

答案是,被导入的是否属于指明的前一级路径的顶级路径以内,否则就会:

import effects.echo
# from sound.effects import echo
ValueError: attempted relative import beyond top-level package

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值