python模块引用梳理

文件组织结构:

复制代码
t
├── __init__.py
├── main.py
├── t1
│ ├── A.py
│ └── __init__.py
└── t2

├── B.py
└── __init__.py

复制代码
A.py

def test():

print 't.t1.A.test()'

B.py

def test():

print 't.t2.B.test()'

执行:

python t/main.py

问题1:

在main.py中引用t2/B的test方法,如何写?

方式1: from xxx import xxx

from t2 import B
B.test()
这个写法很糟糕, 但能解决目前问题。糟糕的地方在于隐晦的引入t2。更好的方式是相对引用。

from .t2 import B
B.test()
但如果用 python t/main.py执行会报错,此处原因请参考这。原因是相对引用默认作为包的方式才能运行。

正确执行方法(linux shell下): python -m t.main

这个写法也不够好!B在具体的代码行,看不出其出处。更好的方式是

from . import t2
t2.B.test()

但运行时会报错!

AttributeError: 'module' object has no attribute 'B'

大致意思是, 模块对象没有B属性!这点从java/.net转过来的也许有一点不习惯!

pythony引入一个模块(import m) <==> 引入m/__init__.py文件,里面有啥就有啥,反之亦然。

破解方法:

1. 不太好的方法有上一个代码例子, 即: from ... import ...2. 在模块的__init__.py文件中自动引入这些文件, 推荐最为最佳实践!此处修改 t/t2/__init__.py文件

import B
这样问题就完美结果了。总结下,最佳实践demo如下:

t/main.py

-- coding:utf-8 --

from . import t2
t2.B.test()
t/t2/__init__.py

-- coding:utf-8 --

from . import B

即:

  1. 相对引用
  2. 尽量引入更顶层包
  3. 通过命名空间引用具体的方法或者类
  4. 被引用包(子包)需要在__init__.py中声明(import)可以被外部直接访问的文件

问题2:

在t2/B中如何引用t1/A的test方法?

t/t2/B.py

from .. import t1
t1.A.test()
同时声明A

t/t1/__init__.py

from . import A


Python包的相对导入时出现错误的解决方法

  在练习Python中package的相对导入时,即

from . import XXX
  或者 

from .. import XXX
  时会遇到这样两个错误:

SystemError: Parent module '' not loaded, cannot perform relative import
  和

ValueError: attempted relative import beyond top-level package

  其实这两个错误的原因归根结底是一样的:在涉及到相对导入时,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。

  举个例子:

  目录树

  testIm/

  --__init__.py

  --main.py : from Tom import tom

  --Tom/

    --__init__.py : print("I'm Tom's __init__!")

    --tom.py : from . import tomBrother, from .. import Kate,print("I'm Tom!")

    --tomBrother.py print(I'm Tom's Brother!)

  --Kate/

    --__init__.py : print("I'm Kate's __init__!")

    --kate.py

  运行文件:main.py

  结果:

复制代码
I'm Tom's __init__!
I'm Tom's Brother!
Traceback (most recent call last):
File "D:PythonLearningTestIm2main.py", line 3, in
from cat import cat
File "D:PythonLearningTestIm2catcat.py", line 4, in
from .. import dog
ValueError: attempted relative import beyond top-level package

复制代码
可以看到from . import tomBrother顺利执行,首先执行了Tom文件夹下的__init__.py文件,后来执行了tomBrother.py文件,但是当执行到“from .. import dog”时报错,这是因为我们是在TestIm文件夹下把main.py文件作为主函数的入口执行的,因此尽管TestIm文件夹中有__init__.py文件,但是该文件夹不能被python解释器视作package,即Tom package不存在上层packge,自然会报错,相对导入时超出了最高层级的package。

修改方法:

目录树

  test/

  --main.py : from testIm.Tom import tom

  --testIm/

    --__init__.py

    --Tom/

      --__init__.py : print("I'm Tom's __init__!")

      --tom.py : from . import tomBrother, from .. import Kate,print("I'm Tom!")

      --tomBrother.py print(I'm Tom's Brother!)

    --Kate/

    --__init__.py : print("I'm Kate's __init__!")

    --kate.py

  运行文件:main.py

结果:  

I'm top's __init__!
I'm Tom's __init__!
I'm Tom's Brother!!
I'm Kate's __init__!
I'm Tom!
即主函数入口不在TestIm中,则TestIm和其同样包含__init__.py文件的子文件夹都被python解释器视作package,形成相应的嵌套关系。可以正常使用from . import XXX和from .. import XXX。

致敬原创:
https://www.cnblogs.com/ArsenalfanInECNU/p/5346751.html
https://www.cnblogs.com/Tommy-Yu/p/5794829.html

python包引用问题相关推荐

  1. python包之间引用_python 子包引用父包和其他子包

    python 子包引用父包和其他子包 python引用子目录很简单, 里面放个__init__.py就可以了. 如何在子目录里面引用其他目录(父目录,爷目录和同辈分目录)呢? 例如: python有项 ...

  2. 【转】python包导入细节

    [转]python包导入细节 包导入格式 导入模块时除了使用模块名进行导入,还可以使用目录名进行导入.例如,在sys.path路径下,有一个dir1/dir2/mod.py模块,那么在任意位置处都可以 ...

  3. Python 包管理工具解惑

    本文转载自http://zengrong.net/post/2169.htm,感谢原作者. 一.困惑 作为一个 Python 初学者,我在包管理上感到相当疑惑(嗯,是困惑).主要表现在下面几个方面: ...

  4. cnocr训练_cnocr: 极简的中文OCR Python包

    Update 2020.04.21: 发布 cnocr V1.1.0 更轻量的 cnocr-V1.1.0 :最小模型只有 6.8M.具体说明见: BreezeDeus:更轻量的 cnocr-V1.1. ...

  5. python包里面的dll是什么_Python中的包ImportError

    前言 Python中的包给我提供了很好的代码组织,相似的功能模块放在同一个包内,不仅代码结构清晰,而且调用起来也比较方便(可以用*导入) 但是,我们在刚开始使用Python包的时候总是会遇到导入错误& ...

  6. python包导入方式_python导包的几种方法(自定义包的生成以及导入详解)

    python 导入数据包的几种方法 1.直接导入整个数据包:improt 数据包 2.导入数据包中的某一个函数: from 数据包 improt 函数(当函数这一项为 * 时为导入整个数据包) 3. ...

  7. studioone精调效果包_cnocr: 极简的中文OCR Python包

    Update 2020.04.21: 发布 cnocr V1.1.0 更轻量的 cnocr-V1.1.0 :最小模型只有 6.8M.具体说明见: BreezeDeus:更轻量的 cnocr-V1.1. ...

  8. python包numpy_NumPy Python科学计算软件包的终极指南

    python包numpy NumPy (pronounced "numb pie") is one of the most important packages to grasp ...

  9. pypi.python.org_在Pypi上发布自己的Python包

    使用Python编程的都知道,Python的包安装非常的方便,一般都是可以pip来安装搞定: sudo pip install 最近因为项目上的需要,发布了一个自己的pypi Python包,这里我大 ...

最新文章

  1. maven2创建或者导入eclipse工程 设置M2_REPO消除错误
  2. 软件工程师的发明家—从发明家的视角分析软件
  3. c语言浮点乘法 溢出,浮点加减乘除运算各在什么情况下会发生溢出?
  4. mysql 给列增加索引
  5. php网页表格样式,HTML5制作表格样式
  6. 从UnitedStack OS 1.0 Preview试用申请问卷调查学习OpenStack
  7. Python 判断字符串是否为IP(字符串中是否包含IP)
  8. Java 判断字符串的存储长度
  9. linux文件被覆盖如何恢复_在Linux下误删文件后恢复
  10. sql数据库性能指标_SQL Server网络性能指标–最重要的指标
  11. 猜数字游戏c语言编程排行榜,C语言程序经典示例—-(7)猜数字游戏
  12. ngrok下载并运行实现内网穿透
  13. PC端自适应使用rem
  14. siv技嘉硬件Linux,Gigabyte技嘉System Information Viewer(SIV)风扇控制软件B20.0529.1版For Win10-64(2020年6月16日发布)...
  15. 活体检测论文研读三:Learning Deep Models for Face Anti-Spoofing: Binary or Auxiliary Supervision
  16. libvirt 的使用
  17. 参考文献中不同符号的含义
  18. 沃伦巴菲特和约尔欧斯汀如何克服公共演讲的恐惧
  19. matlab中cond为啥比bet好,matlab用于超短脉冲中啁啾与色散概念的理解
  20. Linux Debian常用下载工具Transmission和qbittorrent

热门文章

  1. IOS中打开应用实现检查更新的功能
  2. HDU 1711 Number Sequence(KMP算法)
  3. 去除iphone图标的半弧高亮效果
  4. 基础数据结构【四】————环形链表与多项式
  5. spring springboot springcloud常用注解
  6. PHP autoload 函数
  7. 不畏浮云遮望眼--离散数学和组合数学
  8. apache日志分析简介
  9. C#实现对象的Xml格式序列化及反序列化
  10. C#中使用DirectX编程