• 本节主要内容:
    1. from xxx import xxx知识点补充
    2. 包

    一、知识点补充。

      我们现在知道可以使⽤import和from xxx import xxx来导入⼀个模块中的内容. 那有⼀种
    特殊的写法: from xxx import * 我们说此时是把模块中的所有内容都导入. 注意, 如果模块中
    没有写出__all__ 则默认所有内容都导入. 如果写了__all__ 此时导入的内容就是在__all__列表
    中列出来的所有名字.

    # haha.py
    __all__ = ["money", "chi"]
    money = 100
    def chi():
         print("我是吃")
    def he():
         print("我是呵呵")
    
    # test.py from haha import * chi() print(money) # he() # 报错

    二、包

      包是一种通过 ".模块"来组织python模块名称空间的方式。那什么样的东西是包呢?我们创建的每个文件夹都可以被称之为包。但是我们要注意,在python2中规定。包内必须处在__init__.py文件。创建包的目的不是为了运行,而是被导入使用。包知识一种形式而已。包的本质就是一种模块

      为何要使用包?包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来,随着功能越写越多,我们无法将所有功能都放在一个文件中,于是我们使用模块去组织功能,随着模块越来越多,我们需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性

      首先,我们先创建一些包。用来作为接下来的学习。包很好创建。只要有一个文件夹,有__init__.py就可以。

    import os
    os.makedirs('glance/api')
    os.makedirs('glance/cmd')
    os.makedirs('glance/db')
    l = []
    l.append(open('glance/__init__.py','w'))
    l.append(open('glance/api/__init__.py','w'))
    l.append(open('glance/api/policy.py','w'))
    l.append(open('glance/api/versions.py','w'))
    l.append(open('glance/cmd/__init__.py','w'))
    l.append(open('glance/cmd/manage.py','w'))
    l.append(open('glance/db/__init__.py','w'))
    l.append(open('glance/db/models.py','w'))
    map(lambda f:f.close() ,l)
    

      创建好目录结构

      接下来给每个文件中添加一些方法:

    #policy.py
    def get():
         print('from policy.py')
    
    #versions.py
    def create_resource(conf):
         print('from version.py: ',conf)
    
    #manage.py
    def main():
         print('from manage.py')
    
    #models.py
    def register_models(engine):
         print('from models.py: ',engine)
    

      接下来我们在bao中使用包中的内容。并且,我们导入包的时候可以使用import或者

      from xxx import xxx这种形式

      首先看import

    import glance.db.models
    glance.db.models.register_models('mysql')
    

      没问题, 很简单, 我们还可以使⽤from xxx import xxx 来导入包内的模块

    from glance.api.policy import get
    get()

      也很简单, 但是, 要注意. from xxx import xxx这种形式, import后⾯不可以出现"点" 也
    就是说from a.b import c是ok的. 但是 from a import b.c 是错误的。

      好了, 到⽬前为⽌, 简单的包已经可以使⽤了. 那包⾥的__init__.py是什么⻤? 其实. 不论
    我们使⽤哪种⽅式导入⼀个包, 只要是第⼀次导入包或者是包的任何其他部分, 都会先执⾏
    __init__.py⽂件. 这个⽂件可以是空的. 但也可以存放⼀些初始化的代码. (随意在glance中的
    __init__.py都可以进⾏测试)

      那我们之前⽤的from xxx import *还可以⽤么? 可以. 我们要在__init__.py⽂件中给出
    __all__来确定* 导入的内容.

    print("我是glance的__init__.py⽂件. ")
    x = 10
    def hehe():
         print("我是呵呵")
    def haha():
         print("我是哈哈")
    __all__ = ['x', "hehe"]
    

      test.py

    from glance import *
    print(x) # OK
    hehe() # OK
    haha() # 报错. __all__⾥没有这个⻤东⻄
    

      接下来,我们来看一下绝对导入和相对导入,我们的最顶级包glance是写给别人用的。然后再glance包内部也会有彼此之间相互导入的需求,这时候就有绝对导入和相对导入两种方式了。

      1.绝对导入:以glance作为起始

      2.相对导入:用.或者..作为起始

    例如, 我们在glance/api/version.py中使⽤glance/cmd/manage.py

    # 在glance/api/version.py
    #绝对导⼊
    from glance.cmd import manage
    manage.main()
    #相对导⼊
    # 这种情形不可以在versions中启动程序.
    # attempted relative import beyond top-level package
    from ..cmd import manage
    manage.main()

      测试的时候要注意. python包路径跟运⾏脚本所在的⽬录有关系. 说⽩了. 就是你运⾏的
    py⽂件所在的⽬录. 在python中不允许你运⾏的程序导包的时候超过当前包的范围(相对导
    入). 如果使⽤绝对导入. 没有这个问题. 换个说法. 如果你在包内使⽤了相对导入. 那在使⽤该
    包内信息的时候. 只能在包外⾯导入.

      接下来,我们来看一个大坑。比如:我们向在policy中使用verson中的内容。

    # 在policy.py
    import versions

      如果我们程序的入⼝是policy.py 那此时程序是没有任何问题的. 但是如果我们在glance
    外⾯import了glance中的policy就会报错 原因是如果在外⾯访问policy的时候. sys.path中的
    路径就是外⾯. 所以根本就不能直接找到versions模块. 所以⼀定会报错:

    ModuleNotFoundError: No module named 'versions'
    

      在导包出错的时候. ⼀定要先看sys.path 看⼀下是否真的能获取到包的信息. 

      

      最后, 我们看⼀下如何单独导入⼀个包. 

    # 在test.py中
    import glance

      此时导入的glance什么都做不了. 因为在glance中的__init__.py中并没有关于⼦包的加
    载. 此时我们需要在__init__.py中分别取引入⼦包中的内容.
      1. 使⽤绝对路径
      2. 使⽤相对路径

    包的注意事项:

      1. 关于包相关的导入语句也分为import和from xxx import xxx两种, 但⽆论使⽤哪种,
    ⽆论在什么位置, 在导入时都必须遵循⼀个原则: 凡是在导入时d带点的. 点左边都必须是⼀
    个包. 否则报错. 可以带⼀连串的点. 比如a.b.c

      2. import导入⽂件时. 产⽣名称空间中的名字来源于⽂件, import 包, 产⽣的名称空间
    中的名字同样来源于⽂件, 即包下的__init__,py, 导入包本质就是在导入该⽂件。

      3. 包A和包B下有同名模块也不会冲突, 如A.a和B.a来⾃两个名称空间

  • 相关阅读:
    【转】主从同步出现一下错误:Slave_IO_Running: Connecting
    解决Mysql的主从数据库没有同步的两种方法
    xargs命令详解,xargs与管道的区别
    常用的排序算法的时间复杂度和空间复杂度
    IP 地址分类(A、B、C、D、E类)
    SNMP 协议介绍 转载
    TCP首部的TimeStamp时间戳选项 转载
    TCP SACK 介绍 转载
    HTTP header 介绍 转载
    CRT小键盘输入乱码
  • 原文地址:https://www.cnblogs.com/guchenxu/p/10197609.html
Copyright © 2020-2023  润新知