25 Python 包

Python 包

以下为简述。详见python cookbook 模块与包

包,包含一组模块和__init__.py的文件夹。

这项技术有助于解决不同应用程序中使用的模块名称之间命名空间冲突的问题。包是通过使用与其相同的名称创建目录,并在该目录中创建__init__.py。如果需要,可以向该目录中放入其他源文件、编译后的扩展和子包。

按如下方式组织一个包
这里写图片描述

只要第一次导入包中的任何部分,就会执行相应的__init__.py中的代码。这个文件可以为空,也可以包含可执行代码。在import语句执行期间,遇到的所有__init__.py都会执行。如import packet.A.a,先执行packet目录下的__init__.py,然后执行A目录下的__init__.py

在使用包时,如果导入的是模块名,则需要注意,

  1. 导入的是包中的模块,正常使用即可。如

    packet/__init__.pypacket/A/__init__.py均为空

    from packet.A import a   #正常,使用a中的属性,a.attr即可
    import packet.A.a as a       #正常,使用a.attr即可
    from packet.A.a import * #正常,直接使用a中的属性attr即可
  2. 导入的是包,则需要修改__init__.py__init__.py不能为空

    使用该语句时,通常希望将某个包中的所有子模块导入当前命名空间中。但是,由于各个操作系统之间的文件名约定不同(尤其是区分大小写上),Python无法准确地确定各个模块的具体内容。所以,导入包时只会导入与包同路径下的__init__.py中的内容。可利用__all__

    测试如下

    • packet/__init__.py为空时,如

      import packet
      packet.d.attr   #AttributeError: 'module' object has no attribute 'd'
      packet.A.a.attr #AttributeError: 'module' object has no attribute 'A'
      from packet import A
      print A.a.attr  #AttributeError: 'module' object has no attribute 'a'   
    • 修改packet/__init__.py,,内容如下(此时packet/A/__init__.py仍为空)

      import d
      import A
      import packet
      packet.d.attr   #正常
      packet.A.a.attr #AttributeError: 'module' object has no attribute 'a',找到了包A但是找不到模块a.py
      from packet import A
      print A.a.attr  #AttributeError: 'module' object has no attribute 'a'   

      继续修改packet/A/__init__.py,内容如下

      import a
      import packet
      packet.d.attr   #正常
      packet.A.a.attr #正常
      from packet import A
      print A.a.attr  #正常

相对导入

如果包中的模块想要使用同一个包中的模块,如packet/A/a.py想要导入packet/d.py或者packet/B/d.py。为此,需要完全限定名称(如packet.B.d,绝对路径导入)或使用包的相对导入,如

packet/A/a.py导入packet/A/d.py ,packet/A/a.py内容如下

  1. 相对导入

    from . import d                #.代表当前路径         
  2. 绝对导入

    import packet.A.d as d

packet/A/a.py导入packet/d.py,packet/A/a.py内容如下

  1. 相对导入

    from .. import d               #..代表上一层路径
  2. 绝对导入

    import packet.d as d           

packet/A/a.py导入packet/B/d.py,packet/A/a.py内容如下

  1. 相对导入

    from ..B import d              #..B代表上层路径中的B
  2. 绝对导入

    import packet.B.d as d

在包中,要避免使用import module来导入包的子模块,在早期的Python版本中,无法确定import module语句引用的是标准库模块还是包的子模块。相对导入和绝对导入能更加清楚的表明导入意图。

使用相对导入的注意事项,

  1. 相对导入只能使用from module import attr形式的导入语句,import ..B.d这样的语法是不对的;

  2. 相对导入只能在包中使用,不能在用户的应用程序中使用相对导入,

    因为不论是相对导入还是绝对导入,都是相当于当前模块来说的,对于用户的主应用程序,也就是入口文件,模块名总是为__main__, 所以用户的应用程序必须使用绝对导入。package中可以使用相对导入和绝对导入;

  3. 使用相对路径import 的Python脚本不能直接运行,要保证这个模块不是入口文件,只有作为被导入的模块才可以使用相对导入。原因正如手册中描述的,所谓相对路径其实就是相对于当前module的路径,如果直接执行脚本,这个module的name就是__main__, 而不是module原来的name, 这样相对路径也就不是原来的相对路径了,导入就会失败,出现错误“ValueError: Attempted relative import in non-package” ;


转载请标明出处,原文地址(http://blog.csdn.net/lis_12/article/details/53966799).

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

参考网址:

  1. http://www.itnose.net/detail/6232982.html
  2. http://blog.csdn.net/lis_12/article/details/53574885
  3. http://blog.csdn.net/chinaren0001/article/details/7338041
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值