python importlib qpython_Python的import机制
模块与包
在了解 import 之前,有两个概念必须提一下:
模块: 一个 .py 文件就是一个模块(module)
包: __init__.py 文件所在目录就是包(package)
当然,这只是极简版的概念。实际上包是一种特殊的模块,而任何定义了 __path__ 属性的模块都被当做包。只不过,咱们日常使用中并不需要知道这些。
两种形式的 import
import 有两种形式:
import ...
from ... import ...
两者有着很细微的区别,先看几行代码。
from string importascii_lowercaseimportstringimport string.ascii_lowercase
运行后发现最后一行代码报错:ImportError: No module named ascii_lowercase,意思是:“找不到叫 ascii_lowercase 的模块”。第 1 行和第 3 行的区别只在于有没有 from,翻翻语法定义发现有这样的规则:
import ... 后面只能是模块或包
from ... import ... 中,from 后面只能是模块或包,import 后面可以是任何变量
可以简单的记成:第一个空只能填模块或包,第二个空填啥都行。
import 的搜索路径
提问,下面这几行代码的输出结果是多少?
importstringprint(string.ascii_lowercase)
是小写字母吗?那可不一定,如果目录树是这样的:
./├── foo.py
└── string.py
foo.py 所在目录有叫 string.py 的文件,结果就不确定了。因为你不知道 import string 到底是 import 了 ./string.py 还是标准库的 string。为了回答这个问题,我们得了解一下 import 是怎么找到模块的,这个过程比较简单,只有两个步骤:
搜索「内置模块」(built-in module)
搜索 sys.path 中的路径
而 sys.path 在初始化时,又会按照顺序添加以下路径:
foo.py 所在目录(如果是软链接,那么是真正的 foo.py 所在目录)或当前目录;
环境变量 PYTHONPATH中列出的目录(类似环境变量 PATH,由用户定义,默认为空);
site 模块被 import 时添加的路径1(site 会在运行时被自动 import)。
import site 所添加的路径一般是 XXX/site-packages(Ubuntu 上是 XXX/dist-packages),比如在我的机器上是 /usr/local/lib/python2.7/site-packages。同时,通过 pip 安装的包也是保存在这个目录下的。如果懒得记 sys.path的初始化过程,可以简单的认为 import 的查找顺序是:
内置模块
.py 文件所在目录
pip 或 easy_install 安装的包
相对 import 与 绝对 import
相对 import
当项目规模变大,代码复杂度上升的时候,我们通常会把一个一个的 .py 文件组织成一个包,让项目结构更加清晰。这时候 import 又会出现一些问题,比如:一个典型包的目录结构是这样的:
string/├──__init__.py
├── find.py
└── foo.py
如果 string/foo.py 的代码如下:
#string/foo.py
from string importfindprint(find)
那么 python string/foo.py 的运行结果会是下面的哪一个呢?
按我们前面讲的各种规则来推导,因为 foo.py 所在目录 string/ 没有 string 模块(即 string.py),所以 import 的是标准库的 string,答案是后者。不过,如果你把 foo 当成 string 包中的模块运行,即 python -m string.foo,会发现运行结果是前者。同样的语句,却有着两种不同的语义,这无疑加重了咱们的心智负担,总不能每次咱们调试包里的模块时,都去检查一下执行的命令是 python string/foo.py 还是 python -m string.foo 吧?
相对 import 就是专为解决「包内导入」(intra-package import)而出现的。它的使用也很简单,from 的后面跟个 . 就行:
#from string/ import find.py
from . importfind#from string/find.py import *
from .find import *
我们再看个复杂点的例子,有个包的目录结构长这样:
one/├──__init__.py
├── foo.py
└── two/├──__init__.py
├── bar.py
└── three/├──__init__.py
├── dull.py
└── run.py
from . importdullfrom .. importbarfrom ... importfooprint('Go, go, go!')
改成
from .dull import *
from ..bar import *
from ...foo import *
print('Go, go, go!')
结果是一样的。
那么 python string/foo.py 和 python -m string.foo 的运行结果又是怎样呢?运行一下发现,两者的输出分别是:
Traceback (most recent call last):
File"string/foo.py", line 1, in
from . importfind
ValueError: Attempted relativeimport in non-package
原因在于 python string/foo.py 把 foo.py 当成一个单独的脚本来运行,认为 foo.py 不属于任何包,所以此时相对 import 就会报错。也就是说,无论命令行是怎么样的,运行时 import 的语义都统一了,不会再出现运行结果不一致的情况。
python importlib qpython_Python的import机制相关推荐
- python importlib qpython_Python imports指南:Python的导入有更好的理解
声明:如果你每天写Python,你会发现这篇文章中没有新东西. 这是专为那些像运维人员等偶尔使用Python的人以及那些忘记/误用python import的人写的. 尽管如此,代码是用Python ...
- 深入探讨Python的import机制:实现远程导入模块 | CSDN博文精选
来源 | Python编程时光(ID:Python-Time) 所谓的模块导入,是指在一个模块中使用另一个模块的代码的操作,它有利于代码的复用. 也许你看到这个标题,会说我怎么会发这么基础的文章? 与 ...
- 一文搞懂 Python 的 import 机制
一.前言 希望能够让读者一文搞懂 Python 的 import 机制 1.什么是 import 机制? 通常来讲,在一段 Python 代码中去执行引用另一个模块中的代码,就需要使用 Python ...
- python多级目录import_深入理解Python中import机制
大型项目中为了维护方便,通常使用模块化开发,模块化的过程中,就会涉及到各种包或者模块的相互导入,即使是对于有多个项目的Python开发者来说, import 也会让人困惑!本文带你深入了解python ...
- 探究 python import机制、module、package与名字空间
在开始之前,先了解一个内置函数dir(),它可以帮助我们分析一些内部的东西,dir()的描述是: dir(): 函数不带参数时,返回当前范围内的变量.方法和定义的类型列表:带参数时,返回参数的属性.方 ...
- 什么是 Python 的 「内存管理机制」?
什么是内存管理器(what) Python作为一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言,与大多数编程语言不同,Python中的变量无需事先申明,变量无需指定类型,程序员无需关心内存 ...
- Python学习:垃圾回收机制
Python 程序在运行的时候,需要在内存中开辟出一块空间,用于存放运行时产生的临时变量:计算完成后,再将结果输出到永久性存储器中.如果数据量过大,内存空间管理不善就很容易出现 OOM(out of ...
- Python中的字符串驻留机制
字符串驻留机制(引用计数机制): 字符串驻留是一种在内存中仅保存一份相同且不可变字符串的方法. 系统维护interned字典,记录已被驻留的字符串对象. 对于短字符串,将其赋值给多个不同的对象时,内存 ...
- 【Python核心】垃圾回收机制
Python程序在运行的时候,需要在内存中开辟出一块空间用于存放运行时产生的临时变量,计算完成后再将结果输出到永久性存储器中 如果数据量过大,内存空间管理不善就很容易出现OOM(out of memo ...
最新文章
- 画图说明Java String的不变性!可修改字符串不要轻易使用String!
- [云炬创业学笔记]第二章决定成为创业者测试11
- lvalue-xvalue-prvalue
- python正则替换查询_使用Python中的正则表达式进行搜索和替换
- Python实现点击选择验证码破解
- 白鹭php源码,看源码系列之从运行流程开始-Egret社区-教程文档-白鹭引擎-Egret Engine-免费开源HTML5游戏引擎 - Powered by Discuz!...
- CAN通信稳定性开发分析
- CSS表格和设置表格样式
- ps磁性套索工具如何抠图
- 使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)
- 关于 A/B 测试那些事儿
- 主流深度学习框架对比
- linux中PS1变量用法
- midas nfx 2021 r1
- 软考中级系统集成项目管理工程师自学好不好过?
- REBOL脚本快速入门
- unity3d 2d游戏(太空大战)开发笔记
- Flash JEDEC 查看
- ESP32学习笔记(20)——SPI(从机)接口使用
- linux openal,OpenAL的一些知识点
热门文章
- 【重点】LeetCode 24. Swap Nodes in Pairs
- atoi函数:c\c++中把字符串整数转换为int型整数
- 关于三角函数图像的思考
- tf.GraphKeys,tf.add_to_collection() 与 tf.get_collection()
- EXCEL VBAProject密码破解 工作表密码破解
- 解决Office 365应用程序无法正常启动(0X0000142)
- webpack构建工具快速上手指南
- linux下mysql 启动命令
- Ext 学习之 Store
- 946. Validate Stack Sequences验证栈序列