python学习日记(包——package)
简述——包
包是一种通过使用‘.模块名’来组织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来自两个命名空间
- 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/models.py','w'))
- l.append(open('glance/db/__init__.py','w'))
- map(lambda f:f.close() ,l)#同时关闭多个文件
创建目录层次代码
- glance/ #Top-level package
- ├── __init__.py #Initialize the glance package
- ├── api #Subpackage for api
- │ ├── __init__.py
- │ ├── policy.py
- │ └── versions.py
- ├── cmd #Subpackage for cmd
- │ ├── __init__.py
- │ └── manage.py
- └── db #Subpackage for db
- ├── __init__.py
- └── models.py
目录的结构
- #文件内容
- #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)
文件内容
注意事项
1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
3.对比import item 和from item import name的应用场景:
如果我们想直接使用name那必须使用后者。
import
在与包glance同级别的文件中测试
- import glance.api.policy
- glance.api.policy.get()
from...import...
需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
我们在与包glance同级别的文件中测试
- from glance.db import models
- models.register_models('abc')
- from glance.cmd.manage import main
- main()
__init__.py文件
不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。
- with open('glance\__init__.py',encoding='utf-8') as f:
- print(f.readline())
- import glance
from glance.api import *
在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。
此处是想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:
- #在api\__init__.py里
- x = 100
- def f():
- print('from api.__init__.py',x)
- __all__ = ['x','policy','f']
此时我们在与glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。
- from glance.api import *
- policy.get()
- f()
追加(注意)
如果想要这样调用(glance同级文件下)
- import glance
- glance.api.policy.get()
需要在__init__文件里面添加一些初始程序,如下:
- #在glance\__init__.py
- from glance import api
- #在api\__init__.py
- from glance.api import policy
绝对导入(sys.path)和相对导入
概述
ps:在上面追加的基础上↑
我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:
绝对导入:以glance作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py
- 在glance/api/version.py
- #绝对导入
- from glance.cmd import manage
- manage.main()
- #相对导入
- from ..cmd import manage
- manage.main()
测试结果:注意一定要在于glance同级的文件中测试
- from glance.api import versions
注意!!
特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。
比如我们想在glance/api/versions.py中导入glance/api/policy.py,有的人一看这两个模块是在同一个目录下,他是这样做的:
- #在version.py中
- import policy
- policy.get()
没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到。
但是同时,子包中的模块version.py极有可能是被一个glance包同一级别的其他文件导入,比如我们在于glance同级下的一个test.py文件中导入version.py,如下:
- from glance.api import versions
- '''
- 执行结果:
- ImportError: No module named 'policy'
- '''
- '''
- 分析:
- 此时我们导入versions在versions.py中执行
- import policy需要找从sys.path也就是从当前目录找policy.py,
- 这必然是找不到的
- '''
————————分割线————————
- glance/
- ├── __init__.py from glance import api
- from glance import cmd
- from glance import db
- ├── api
- │ ├── __init__.py from glance.api import policy
- from glance.api import versions
- │ ├── policy.py
- │ └── versions.py
- ├── cmd from glance.cmd import manage
- │ ├── __init__.py
- │ └── manage.py
- └── db from glance.db import models
- ├── __init__.py
- └── models.py
绝对导入
- glance/
- ├── __init__.py from . import api #.表示当前目录
- from . import cmd
- from . import db
- ├── api
- │ ├── __init__.py from . import policy
- from . import versions
- │ ├── policy.py
- │ └── versions.py
- ├── cmd from . import manage
- │ ├── __init__.py
- │ └── manage.py from ..api import policy
- #..表示上一级目录,想再manage中使用policy中的方法就需要回到上一级glance目录往下找api包,从api导入policy
- └── db from . import models
- ├── __init__.py
- └── models.py
相对导入
单独导入包
单独导入的结果
单独导入包名称时不会导入包中所有包含的所有子模块,如
- import glance
- glance.api.policy.get()
解决方法:
- #在glance\__init__.py
- from . import api
- #在api\__init__.py
- from . import policy
重新执行代码就OK了。
import glance之后直接调用模块中的方法
- glance/
- ├── __init__.py from .api import *
- from .cmd import *
- from .db import *
- ├── api
- │ ├── __init__.py __all__ = ['policy','versions']
- │ ├── policy.py
- │ └── versions.py
- ├── cmd __all__ = ['manage']
- │ ├── __init__.py
- │ └── manage.py
- └── db __all__ = ['models']
- ├── __init__.py
- └── models.py
- import glance
- policy.get()#好像不行?
- import glance
- glance.policy.get()#
pass
python学习日记(包——package)的更多相关文章
- Python 学习日记(第三周)
知识回顾 在上一周的学习里,我学习了一些学习Python的基础知识下面先简短的回顾一些: 1Python的版本和和安装 Python的版本主要有2.x和3.x两个版本这两个版本在语法等方面有一定的区别 ...
- Python学习日记 --day2
Python学习日记 --day2 1.格式化输出:% s d (%为占位符 s为字符串类型 d为数字类型) name = input('请输入姓名') age = int(input('请输入年龄 ...
- python学习日记(基础数据类型及其方法01)
数字 int 主要是用于计算的,常用的方法有一种 #既十进制数值用二进制表示时,最少使用的位数i = 3#3的ASCII为:0000 0011,即两位 s = i.bit_length() print ...
- Python学习 之 包和模块
1.rpm -ql python #查看python在计算机中安装了哪些文件 2.模块是一个可以导入的Python脚本文件 包是一堆按目录组织的模块和子包,目录下的__init__.py文件存放了包的 ...
- Python学习日记(一):拜见小主——Python
近日学习Python,特将学习过程及一点心得记录于此. 由于之前做过一个Java爬虫的项目,虽然很长时间没有碰过爬虫,但是小郭同学有一颗不死的爬虫心,哈哈.最近在互联网上找一些电影的时候,有很多电影只 ...
- Python学习日记(三十一) 黏包问题
import subprocess res = subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE,stderr=subprocess.P ...
- Python学习日记
江林楠学习了一下午后给大家呈现的20分钟速成Python—— 一些基本的语法:1.python无变量声明 直接a = []即可.2.python为对齐语言,用制表符表示语句块的嵌套.3.python语 ...
- 从CentOS安装完成到生成词云python学习日记
欢迎访问我的个人博客:原文链接 前言 人生苦短,我用python.学习python怎么能不搞一下词云呢是不是(ง •̀_•́)ง 于是便有了这篇边实践边记录的笔记. 环境:VMware 12pro + ...
- python学习日记(常用模块)
模块概念 什么是模块 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代 ...
随机推荐
- .net接收post请求,并转为字符串
Stream s = Request.InputStream; int count = 0; byte[] buffer = new byte[1024]; StringBuilder reqXml ...
- day08 Html
<del>我被删除了</del> <!--delete--> <b>我是粗体</b> <!-- bold --> <i&g ...
- spring cloud feign 文件上传和文件下载
文件上传参考文档:http://blog.didispace.com/spring-cloud-starter-dalston-2-4/ 文件下载参考文档:https://blog.csdn.net/ ...
- JavaScript学习一之数据校验
JavaScript页面进行数据校验 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
- animate-queue和step-animate
Step-animate: 分为3部分:{配置},{step:function(){...},duration:1000} <div id="warpper" style=& ...
- Your project path contains non-ASCII characters
Android studio导入project时报错 non-ASCII characters意味着中文字符报错,解决方法简单有效: 检查项目路径中是否出现中文名,将中文字符修改成英文就可以解决辽~
- 在chrome 怎么通过ajax请求加载本地文件
在chrome下面用Jquery 的load方法加载本地的html文件时会报错 我百度了一下是因为 谷歌浏览器内核为了安全机制,不允许这样方式访问其他页面,但是可以通过加 --enable-file- ...
- centos 7 selinux开启关闭
1 查看selinux状态 [root@localhost ~]# sestatus SELinux status: disabled 2 关闭 零时关闭 [root@localhost ~]# se ...
- Java 疑问自问自答
1.为什么把关闭资源放finally中? 答:保证即使前面发生一些异常情况也会最终正常执行finally中的代码,用于保证资源释放. 来源:https://bbs.csdn.net/topics/36 ...
- log4net:ERROR XmlHierarchyConfigurator: Cannot find Property [File] to set object on [TF.Log.FileAppender]
难受,香菇. 大概研究了两个多小时,搜了很多资料都没有很完美的答案,最后突然脑子就一闪一闪,才弄明白咋回事. log4net:ERROR XmlHierarchyConfigurator: Canno ...