python包

python包

       一个模块就是一个python文件,在python里为了对模块分类管理,就需要划分不同的文件夹。多个有联系的模块可以放在同一个文件夹下,为了称呼方便,一般把python里的一个代码文件夹称为一个包。

一、包的定义

       现有以下包:newmsg,包里有三个模块,分别是__init__.py、sendmsg.py、recvmsg.py文件。在包的同级有个test.py文件,目标是在test.py文件里引入newmsg的两个模块sendmsg.py和recvmsg.py。

       

需要强调的是:

  1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错

  2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是模块的一种形式

二、包的使用

       sendmsg.py文件里的内容如下:

def send_msg():
    print('——————sendmsg方法被调用了——————')

  recvmsg.py文件里的内容如下:

def recv_msg():
    print('——————recvmsg方法被调用了——————')

  可以使用以下几种方法来导入模块,使用模块里的方法:

       1、直接使用包名.模块名导入指定的模块

import newmsg.sendmsg
newmsg.sendmsg.send_msg()

       2、使用from xxx improt xxx 方式导入指定模块

from newsmsg import sendmsg,recvmsg
sendmsg.send_msg()     #此时不需要写包名,直接写模块名
recvmsg.recv_msg()

       3、使用__init__.py ,导入包里的指定模块。

          

          在__init__.py文件里编写代码:

from . import sendmsg     #导入指定的模块     .代表的是当前文件夹

  test.py文件里的代码:

import newmsg     #导入时,只需要输入包名即可。在包名的__init__.py文件里,导入了指定模块
newmsg.sendmsg.send_msg()   #可以直接调用对应的方法
newmsg.recvmsg.recv_msg()    #报错,不可以使用recvmsg模块,因为__init__.py文件没有导入这个模块

  包属于模块的一种,因而包以及包内的模块均是用来被导入使用的,而绝非被直接执行,首次导入包(如import newmsg)同样会做三件事:

       1、执行包下的__init__.py文件

       2、产生一个新的名称空间用于存放__init__.py执行过程中产生的名字

       3、在当前执行文件所在的名称空间中得到一个名字newmsg,该名字指向__init__.py的名称空间,例如newmsg.xxx和newmsg.yyy中的xxx和yyy都是来自于newmsg下的__init__.py,也就是说导入包时并不会导入包下所有的子模块与子包

       4、newmsg.sendmsg.send_msg() 要求newmsg下有名字sendmsg,进而newmsg.sendmsg下有名字send_msg。newmsg.sendmsg下已经有名字send_msg了,但newmsg下没有名字sendmsg,因此需要在包中的__init__.py文件中导入模块sendmsg(from . import sendmsg

       5、关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如import 顶级包.子包.子模块,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

       6、包A和包B下有同名模块也不会冲突,如A.a与B.a来自两个命名空间。

       7、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件


        3.1绝对导入与相对导入

       针对包内的模块之间互相导入,导入的方式有两种:

       a、绝对导入:以顶级包为起始(因为包已经被使用者放入sys.path路径中)

# newmsg下的__init__.py
from newmsg import recvmsg

  b、相对导入:表示当前文件所在目录,.. 代表当前目录的上一级目录,以此类推

# newmsg下的__init__.py
from . import recvmsg

  同理,针对package1.package2.moudle.fuction(),则需要

# 操作package1下的__init__.py,保证package1.package2
from . import package2  或 from package1 import package2

#操作package2下的__init__.py,保证package1.package2.moudle
from . import moudle  或 from package1.package2 import moudle

  针对包内部模块之间的相互导入推荐使用相对导入,需要特别强调:

  • 相对导入只能在包内部使用,用相对导导入不同目录下的模块是非法的(包内模块之间的导入,推荐使用相对导入)
  • 无论是import还是from-import,但凡是在导入时带点的,点的左边必须是包,否则语法错误

  • 相对导入不能跨出包,所以相对导入仅限于包内模板彼此之间使用
  • 绝对导入是没有任何限制的,所以绝对导入是一种通用的导入方式

       3.2__init__.py其他用途

       __init__.py控制着包的导入行为。__init__.py为空仅仅是把这个包导入,不会导入包中的模块。可以在__init__.py文件中编写内容。
 
       __init__.py文件内容:
print('hello,wold!')

       别的模块在引入这个包的时候,会自动调用这段代码:

from newmsg import sendmsg,recvmsg
sendmsg.send_msg()  

       运行结果:
           hello world!
           ——————sendmsg方法被调用了——————
 

       3.3__all__变量的使用

        在__init__.py文件中,定义一个__all__变量,它控制着from 包名 import * 时导入的模块。

        __init__.py文件:

__all__=['sendmsg']

  test.py文件

from newmsg import *
sendmsg.send_msg()
recvmsg.recv_msg()     #报错,recvmsg模块没被导入

     

posted @ 2021-03-04 20:32  wangshanglinju  阅读(219)  评论(0编辑  收藏  举报