首页 > 其他 > 详细

(二十五)包

时间:2018-12-29 22:10:16      阅读:168      评论:0      收藏:0      [点我收藏+]

  包是?种通过 ‘.模块名‘来组织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)

#接下来. 我们在test中使?包中的内容. 并且, 我们导入包的时候可以使?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两种, 但?论使?哪种,?论在什么位置,在导入时都必须遵循?个原则: 凡是在导入时带点的,点左边都必须是?

 个包,否则报错,可以带?连串的点,比如a.b.c。

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

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

 

(二十五)包

原文:https://www.cnblogs.com/asia-yang/p/10197986.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!