Python中的namespace package
在Python 3.3之前,一个目录想被当成package被导入,必须包含__init__.py文件;而在Python 3.3及以后的版本中,__init__.py文件可以不需要,直接使用import后者from语法,就能直接导入目录,这样的目录称为namespace package。
换句话说,>=Python 3.3之后,存在两种package,一种是常规的package,即包含__init__.py的目录,一种是namespace package,即不包含__init__.py的目录。
搜寻规则
当引入namespace package之后,Python的搜寻规则总结如下(这里以绝对导入为例,如果是相对导入,sys.path换成当前目录即可):
1 如果按照sys.path的路径搜寻到一个常规的package,那么Python导入这个package,本次搜寻返回;
2 如果按照sys.path的路径搜寻到一个module文件,那么导入这个文件,本次搜寻返回;
3 如果按照sys.path的路径搜寻到一个目录,并且不包含__init__.py文件,那么就将这个目录记录下来(即namespace package),同时继续按照sys.path中下一个路径开始搜寻
4 如果经过1,2,3步骤都没有搜寻到指定的目录,那么,继续按照sys.path中的一个路径开始搜寻
当遍历完成所有的sys.path中的路径,同时也没有发现常规的package和module文件,那么,就按照namespace package的__path__属性包含的路径,再进行一次搜寻,如果找到,就导入,否则,导入失败。
换句话说,namespace package中__path__属性包含的路径,起到了类似sys.path的作用。
举例来说,加入有如下目录结构:
# 当前目录是/home/username/python
mkdir -p ns/dir1/sub
mkdir -p ns/dir2/sub
在ns/dir1/sub目录下有文件mod1.py:
# ns/dir1/sub/mod1.py
print(r'dir1\sub\mod1')
在ns/dir2/sub目录下有文件mod2.py
# ns/dir2/sub/mod2.py
print(r'dir2\sub\mod2')
为了让sys.path中包含路径/home/username/python/ns/dir1和/home/username/python/dir2,我们进行如下设置:
export PYTHONPATH=/home/username/python/ns/dir1:/home/username/python/dir2
在/home/username/python目录下进入Python交互式命令行:
>>>import sys
>>>import sys.path #可以看到上述设置的路径生效了
['', '/home/username/python/ns/dir1', '/home/chaochao/python/ns/dir2',...] >>>import sub # sub被当成是一个namespace package
<module 'sub' (namespace)> >>>sub.__path__ #__path__属性中记录了两个路径,后续的查找从这两个路径开始
_NamespacePath(['/home/chaochao/python/ns/dir1/sub', '/home/chaochao/python/ns/dir2/sub']) >>>from sub import mod1 #成功导入mod1.py
dir1\sub\mod1 >>>from sub import mod2 #成功导入mod2.py
dir2\sub\mo2
需要指出的是,对于namespace package,相对导入的语法也是可以使用的,没有任何变化;同时,常规package和namespace package也是可以相互包含的,不会有任何影响。
Python中的namespace package的更多相关文章
- python中的namespace
python中的名称空间是名称(标识符)到对象的映射. 具体来说,python为模块.函数.类.对象保存一个字典(__dict__),里面就是重名称到对象的映射. 可以参看下面python程序的输出: ...
- [Python]Python中的包(Package)
参考官方文档中的Module和Glosssary中的描述.Module: https://docs.python.org/3/tutorial/modules.html#packagesGlossar ...
- Python中包(package)的调用方式
一.什么是Python Package 如何区分你看到的目录是一个Python Package包呢?其实很简单,你只要看这个名录下是否有“__init__.py”这个文件就好了,如果有那么就是Pyt ...
- python中os.path 与sys.path
看别人写的代码,会发现两个和路径设置有关的模块 os 和sys.我对这两个模块也不是特别了解.只是记录一下自己看到的,学到的. python 中我们会使用这两个模块和文件路径, 创建文件 之类的 操作 ...
- ## Python中的Package和Jupyter中import包问题
前言 关于python包的一些知识 Java中的package概念 我们知道在java中的import package概念, java中的包就是一个目录,里面包含着子目录,子目录套着子目录,当需要引入 ...
- Python中模块(Module)和包(Package)的区别
本文绝大部分内容转载至:廖雪峰官方网站 1. 模块(Module) 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函 ...
- Python中package的导入语法
在Python中,一个目录被称为一个package.import和from语法除了导入module文件之外,还可以导入package,语法如下: # import语法 import dir1.dir2 ...
- python中__init__.py的作用、module和package
控制包的导入行为: 1.声明当前文件是一个可导入的包: 2.如果当下包下有多个.py文件使用__ all__ = [ '模块名'],也就是form XXX import YYY module和pack ...
- Python中的内置函数
2.1 Built-in Functions The Python interpreter has a number of functions built into it that are alway ...
随机推荐
- python初学者日记01(字符串操作方法)
时间:2018/12/16 作者:永远的码农(博客园) 环境: win10,pycharm2018,python3.7.1 1.1 基础操作(交互输入输出) input = input(" ...
- CentOS 6.8安装Ceph
机器规划 IP 主机名 角色 10.101.0.1 ceph01 mon admin mds 10.101.0.2 ceph02 ods 10.101.0.3 ceph03 ods 10.101.0. ...
- 让 shell(bash) 命令行显示当前 git 的分支名称
早上测试脚本的时候,偶然在这篇文章<Git – setting up a remote repository and doing an initial push>看到一个关于 git 的好 ...
- Hibernate 事务不回滚
问题: 这几天在做开发时,发现事务不回滚了,Service是用AOP加的事务,数据库是MySql, 表全部是InnoDB: 方法回滚是采用spring的手动回滚: ...
- yii学习笔记(1),目录结构和请求过程
最近找找工作面试,发现很多要求会yii.于是准备学习一个新的框架 先在腾讯课堂找了个视频看了一下,然后去网上现在了“归档文件”(还有一种方式是通过php的包管理工具“composer”安装) 归档文件 ...
- Docker之centos 简单安装
centos6因为系统自带的可执行的应用程序与 docker 包名字发生冲突,所以重新命名 docker 的RPM包名字为 docker-io. 首先卸载docker包 sudo yum -y rem ...
- Flink的部署
Flink的部署 环境准备:windows7系统,本地连接.如果打开更改适配器设置后没有本地连接,可以通过驱动精灵等软件安装网卡驱动.为了使部署在虚拟机上的服务器可以与物理机进行连通,必须使物理机的网 ...
- STM32(11)——DMA
简介: DMA:Direct Memory Access,直接存储器访问.DMA传输数据从一个地址空间复制到另外一个地址空间.当CPU初始化这个传输动作,传输动作本身就是DMA控制器来实现和完成.典型 ...
- 插入排序,C语言实现
插入排序是稳定排序,时间复杂度最低为O(n),最高为O(n^2),平均为O(n^2). 插入排序是将数组分为两部分,一部分已经排好序,另一部分未排好序,每次从未排好序的部分取第一个元素插入到已经排好序 ...
- 树莓派编译程序时报错:virtual memory exhausted: Cannot allocate memory
一.原因分析: 树莓派内存太小,编译程序会出现virtual memory exhausted: Cannot allocate memory的问题,可以用swap扩展内存的方法. 二.解决方法: 安 ...