简述——包

包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

注意:

1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法

2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)

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

强调:

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

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

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

  1. import os
  2. os.makedirs('glance/api')
  3. os.makedirs('glance/cmd')
  4. os.makedirs('glance/db')
  5. l = []#注意列表的用法与作用
  6. l.append(open('glance/__init__.py','w'))
  7. l.append(open('glance/api/__init__.py','w'))
  8. l.append(open('glance/api/policy.py','w'))
  9. l.append(open('glance/api/versions.py','w'))
  10. l.append(open('glance/cmd/__init__.py','w'))
  11. l.append(open('glance/cmd/manage.py','w'))
  12. l.append(open('glance/db/models.py','w'))
  13. l.append(open('glance/db/__init__.py','w'))
  14. map(lambda f:f.close() ,l)#同时关闭多个文件

创建目录层次代码

  1. glance/ #Top-level package
  2.  
  3. ├── __init__.py #Initialize the glance package
  4.  
  5. ├── api #Subpackage for api
  6.  
  7. ├── __init__.py
  8.  
  9. ├── policy.py
  10.  
  11. └── versions.py
  12.  
  13. ├── cmd #Subpackage for cmd
  14.  
  15. ├── __init__.py
  16.  
  17. └── manage.py
  18.  
  19. └── db #Subpackage for db
  20.  
  21. ├── __init__.py
  22.  
  23. └── models.py

目录的结构

  1. #文件内容
  2.  
  3. #policy.py
  4. def get():
  5. print('from policy.py')
  6.  
  7. #versions.py
  8. def create_resource(conf):
  9. print('from version.py: ',conf)
  10.  
  11. #manage.py
  12. def main():
  13. print('from manage.py')
  14.  
  15. #models.py
  16. def register_models(engine):
  17. print('from models.py: ',engine)

文件内容

注意事项

1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。

2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

3.对比import item 和from item import name的应用场景:
如果我们想直接使用name那必须使用后者。

import

在与包glance同级别的文件中测试

  1. import glance.api.policy
  2. glance.api.policy.get()

from...import...

需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法

我们在与包glance同级别的文件中测试

  1. from glance.db import models
  2. models.register_models('abc')
  3.  
  4. from glance.cmd.manage import main
  5. main()

__init__.py文件

不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。

  1. with open('glance\__init__.py',encoding='utf-8') as f:
  2. print(f.readline())
  3.  
  4. import glance

from glance.api import *

在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。

此处是想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:

  1. #在api\__init__.py里
  2. x = 100
  3. def f():
  4. print('from api.__init__.py',x)
  5. __all__ = ['x','policy','f']

此时我们在与glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。

  1. from glance.api import *
  2. policy.get()
  3. f()

追加(注意)

如果想要这样调用(glance同级文件下)

  1. import glance
  2. glance.api.policy.get()

需要在__init__文件里面添加一些初始程序,如下:

  1. #在glance\__init__.py
  2. from glance import api
  3.  
  4. #在api\__init__.py
  5. from glance.api import policy

绝对导入(sys.path)和相对导入

概述

ps:在上面追加的基础上↑

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

绝对导入:以glance作为起始

相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

  1. glance/api/version.py
  2.  
  3. #绝对导入
  4. from glance.cmd import manage
  5. manage.main()
  6.  
  7. #相对导入
  8. from ..cmd import manage
  9. manage.main()

测试结果:注意一定要在于glance同级的文件中测试

  1. from glance.api import versions

注意!!

特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。

比如我们想在glance/api/versions.py中导入glance/api/policy.py,有的人一看这两个模块是在同一个目录下,他是这样做的:

  1. #在version.py中
  2.  
  3. import policy
  4. policy.get()

没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到。

但是同时,子包中的模块version.py极有可能是被一个glance包同一级别的其他文件导入,比如我们在于glance同级下的一个test.py文件中导入version.py,如下:

  1. from glance.api import versions
  2.  
  3. '''
  4. 执行结果:
  5. ImportError: No module named 'policy'
  6. '''
  7.  
  8. '''
  9. 分析:
  10. 此时我们导入versions在versions.py中执行
  11. import policy需要找从sys.path也就是从当前目录找policy.py,
  12. 这必然是找不到的
  13. '''

————————分割线————————

  1. glance/
  2.  
  3. ├── __init__.py from glance import api
  4. from glance import cmd
  5. from glance import db
  6.  
  7. ├── api
  8.  
  9. ├── __init__.py from glance.api import policy
  10. from glance.api import versions
  11.  
  12. ├── policy.py
  13.  
  14. └── versions.py
  15.  
  16. ├── cmd from glance.cmd import manage
  17.  
  18. ├── __init__.py
  19.  
  20. └── manage.py
  21.  
  22. └── db from glance.db import models
  23.  
  24. ├── __init__.py
  25.  
  26. └── models.py

绝对导入

  1. glance/
  2.  
  3. ├── __init__.py from . import api #.表示当前目录
  4. from . import cmd
  5. from . import db
  6.  
  7. ├── api
  8.  
  9. ├── __init__.py from . import policy
  10. from . import versions
  11.  
  12. ├── policy.py
  13.  
  14. └── versions.py
  15.  
  16. ├── cmd from . import manage
  17.  
  18. ├── __init__.py
  19.  
  20. └── manage.py from ..api import policy
  21. #..表示上一级目录,想再manage中使用policy中的方法就需要回到上一级glance目录往下找api包,从api导入policy
  22.  
  23. └── db from . import models
  24.  
  25. ├── __init__.py
  26.  
  27. └── models.py

相对导入

单独导入包

单独导入的结果

单独导入包名称时不会导入包中所有包含的所有子模块,如

  1. import glance
  2. glance.api.policy.get()

解决方法:

  1. #在glance\__init__.py
  2. from . import api
  3.  
  4. #在api\__init__.py
  5. from . import policy

重新执行代码就OK了。

import glance之后直接调用模块中的方法

  1. glance/
  2.  
  3. ├── __init__.py from .api import *
  4. from .cmd import *
  5. from .db import *
  6. ├── api
  7.  
  8. ├── __init__.py __all__ = ['policy','versions']
  9.  
  10. ├── policy.py
  11.  
  12. └── versions.py
  13.  
  14. ├── cmd __all__ = ['manage']
  15.  
  16. ├── __init__.py
  17.  
  18. └── manage.py
  19.  
  20. └── db __all__ = ['models']
  21.  
  22. ├── __init__.py
  23.  
  24. └── models.py
  25.  
  26. import glance
  27. policy.get()#好像不行?
  28. import glance
  29. glance.policy.get()#

pass

python学习日记(包——package)的更多相关文章

  1. Python 学习日记(第三周)

    知识回顾 在上一周的学习里,我学习了一些学习Python的基础知识下面先简短的回顾一些: 1Python的版本和和安装 Python的版本主要有2.x和3.x两个版本这两个版本在语法等方面有一定的区别 ...

  2. Python学习日记 --day2

    Python学习日记 --day2 1.格式化输出:% s d  (%为占位符 s为字符串类型 d为数字类型) name = input('请输入姓名') age = int(input('请输入年龄 ...

  3. python学习日记(基础数据类型及其方法01)

    数字 int 主要是用于计算的,常用的方法有一种 #既十进制数值用二进制表示时,最少使用的位数i = 3#3的ASCII为:0000 0011,即两位 s = i.bit_length() print ...

  4. Python学习 之 包和模块

    1.rpm -ql python #查看python在计算机中安装了哪些文件 2.模块是一个可以导入的Python脚本文件 包是一堆按目录组织的模块和子包,目录下的__init__.py文件存放了包的 ...

  5. Python学习日记(一):拜见小主——Python

    近日学习Python,特将学习过程及一点心得记录于此. 由于之前做过一个Java爬虫的项目,虽然很长时间没有碰过爬虫,但是小郭同学有一颗不死的爬虫心,哈哈.最近在互联网上找一些电影的时候,有很多电影只 ...

  6. Python学习日记(三十一) 黏包问题

    import subprocess res = subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE,stderr=subprocess.P ...

  7. Python学习日记

    江林楠学习了一下午后给大家呈现的20分钟速成Python—— 一些基本的语法:1.python无变量声明 直接a = []即可.2.python为对齐语言,用制表符表示语句块的嵌套.3.python语 ...

  8. 从CentOS安装完成到生成词云python学习日记

    欢迎访问我的个人博客:原文链接 前言 人生苦短,我用python.学习python怎么能不搞一下词云呢是不是(ง •̀_•́)ง 于是便有了这篇边实践边记录的笔记. 环境:VMware 12pro + ...

  9. python学习日记(常用模块)

    模块概念 什么是模块 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代 ...

随机推荐

  1. .net接收post请求,并转为字符串

    Stream s = Request.InputStream; int count = 0; byte[] buffer = new byte[1024]; StringBuilder reqXml ...

  2. day08 Html

    <del>我被删除了</del> <!--delete--> <b>我是粗体</b> <!-- bold --> <i&g ...

  3. spring cloud feign 文件上传和文件下载

    文件上传参考文档:http://blog.didispace.com/spring-cloud-starter-dalston-2-4/ 文件下载参考文档:https://blog.csdn.net/ ...

  4. JavaScript学习一之数据校验

    JavaScript页面进行数据校验 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...

  5. animate-queue和step-animate

    Step-animate: 分为3部分:{配置},{step:function(){...},duration:1000} <div id="warpper" style=& ...

  6. Your project path contains non-ASCII characters

    Android studio导入project时报错 non-ASCII characters意味着中文字符报错,解决方法简单有效: 检查项目路径中是否出现中文名,将中文字符修改成英文就可以解决辽~

  7. 在chrome 怎么通过ajax请求加载本地文件

    在chrome下面用Jquery 的load方法加载本地的html文件时会报错 我百度了一下是因为 谷歌浏览器内核为了安全机制,不允许这样方式访问其他页面,但是可以通过加 --enable-file- ...

  8. centos 7 selinux开启关闭

    1 查看selinux状态 [root@localhost ~]# sestatus SELinux status: disabled 2 关闭 零时关闭 [root@localhost ~]# se ...

  9. Java 疑问自问自答

    1.为什么把关闭资源放finally中? 答:保证即使前面发生一些异常情况也会最终正常执行finally中的代码,用于保证资源释放. 来源:https://bbs.csdn.net/topics/36 ...

  10. log4net:ERROR XmlHierarchyConfigurator: Cannot find Property [File] to set object on [TF.Log.FileAppender]

    难受,香菇. 大概研究了两个多小时,搜了很多资料都没有很完美的答案,最后突然脑子就一闪一闪,才弄明白咋回事. log4net:ERROR XmlHierarchyConfigurator: Canno ...