imp
--访问 import 内构件¶
源代码: Lib/imp.py
该模块提供了一个接口,用于实现 import
语句。它定义了以下常量和函数:
- imp.get_magic()¶
返回用于识别字节编译代码文件的神奇字符串值 (
.pyc
文件)。(对于每个Python版本,此值可能不同。)3.4 版后已移除: 使用
importlib.util.MAGIC_NUMBER
相反。
- imp.get_suffixes()¶
返回三元素元组的列表,每个元组描述特定类型的模块。每三个都有形式
(suffix, mode, type)
在哪里 后缀 是要附加到模块名称以形成要搜索的文件名的字符串, mode 是要传递给内置open()
函数打开文件(可以'r'
对于文本文件或'rb'
对于二进制文件),以及 type 是文件类型,它具有以下值之一PY_SOURCE
,PY_COMPILED
或C_EXTENSION
,如下所述。3.3 版后已移除: 使用上定义的常量
importlib.machinery
相反。
- imp.find_module(name[, path])¶
试着找到模块 name . 如果 path 被省略或
None
,目录名列表sys.path
搜索,但首先搜索一些特殊的地方:函数尝试查找具有给定名称的内置模块 (C_BUILTIN
,然后是冻结模块 (PY_FROZEN
在某些系统上,也会查找其他一些位置(在Windows上,它会在注册表中查找可能指向特定文件的位置)。否则, path 必须是一个目录名列表;每个目录都会搜索包含由返回的任何后缀的文件
get_suffixes()
上面。列表中的无效名称将被静默忽略(但所有列表项都必须是字符串)。如果搜索成功,返回值为3元素元组
(file, pathname, description)
:file 是公开的 file object 在开始的时候, 路径名 是否找到文件的路径名,以及 description 是包含在由返回的列表中的3元素元组
get_suffixes()
描述找到的模块类型。如果模块是内置的或冻结的,则 file 和 路径名 都是
None
以及 描述 元组的后缀和模式包含空字符串;模块类型如上面括号中所示。如果搜索失败,ImportError
提高了。其他异常表示参数或环境有问题。如果模块是一个包, file 是
None
, 路径名 是包路径和 description 元组是PKG_DIRECTORY
.此函数不处理分层模块名称(包含点的名称)。为了找到 P.M 也就是说,子模块 M 封装的 P 使用
find_module()
和load_module()
查找和加载包 P 然后使用find_module()
与 path 参数设置为P.__path__
. 什么时候? P 它本身有一个点名称,递归地应用这个配方。3.3 版后已移除: 使用
importlib.util.find_spec()
相反,除非需要与python 3.3兼容,在这种情况下使用importlib.find_loader()
. 例如,前一个案例的用法,请参见 实例 剖面图importlib
文档。
- imp.load_module(name, file, pathname, description)¶
加载以前由找到的模块
find_module()
(或通过其他方式进行的搜索产生兼容结果)。此功能不仅仅用于导入模块:如果模块已经导入,它将重新加载模块!这个 name 参数指示模块的完整名称(包括包名称,如果这是包的子模块)。这个 file 参数是打开的文件,并且 路径名 是相应的文件名;可以是None
和''
当模块是包或不是从文件加载时。这个 description 参数是一个元组,将由返回get_suffixes()
,描述必须加载的模块类型。如果加载成功,返回值是模块对象;否则,异常(通常
ImportError
)。重要: 调用方负责关闭 file 参数,如果不是的话
None
,即使引发异常。最好使用try
…finally
语句。3.3 版后已移除: 如果以前与
imp.find_module()
然后考虑使用importlib.import_module()
,否则使用所选替换返回的加载程序imp.find_module()
. 如果你调用imp.load_module()
以及直接使用文件路径参数的相关函数,然后使用importlib.util.spec_from_file_location()
和importlib.util.module_from_spec()
. 见 实例 剖面图importlib
各种方法的详细说明文件。
- imp.new_module(name)¶
返回名为 name . 这个对象是 not 插入
sys.modules
.3.4 版后已移除: 使用
importlib.util.module_from_spec()
相反。
- imp.reload(module)¶
重新加载以前导入的 模块 . 参数必须是一个模块对象,因此它以前必须成功导入。如果您已经使用外部编辑器编辑了模块源文件,并且希望在不离开Python解释器的情况下试用新版本,那么这将非常有用。返回值是模块对象(与 模块 参数)。
什么时候?
reload(module)
执行:python模块的代码被重新编译,模块级代码被重新执行,定义了一组绑定到模块字典中名称的新对象。这个
init
扩展模块的函数没有第二次调用。与Python中的所有其他对象一样,旧对象只有在其引用计数降至零后才会被回收。
模块命名空间中的名称将更新为指向任何新对象或更改的对象。
对旧对象的其他引用(如模块外部的名称)不会反弹以引用新对象,如果需要,则必须在出现新对象的每个命名空间中进行更新。
还有许多其他注意事项:
当模块重新加载时,它的字典(包含模块的全局变量)将被保留。重新定义名称将覆盖旧的定义,因此这通常不是问题。如果模块的新版本未定义由旧版本定义的名称,则保留旧定义。如果模块维护对象的全局表或缓存,则可以利用此功能
try
语句,它可以测试表是否存在,如果需要,则跳过其初始化::try: cache except NameError: cache = {}
虽然重新加载内置或动态加载的模块通常不是很有用,但是
sys
,__main__
和builtins
. 然而,在许多情况下,扩展模块的设计不能被多次初始化,并且在重新加载时可能以任意方式失败。如果某个模块使用
from
…import
……调用reload()
因为另一个模块没有重新定义从它导入的对象——一种方法是重新执行from
声明,另一个是使用import
和限定名( 模块 . name 相反。如果一个模块实例化一个类的实例,那么重新加载定义该类的模块不会影响实例的方法定义——它们继续使用旧的类定义。派生类也是如此。
在 3.3 版更改: 依赖于两者
__name__
和__loader__
在正在重新加载的模块上定义,而不是__name__
.3.4 版后已移除: 使用
importlib.reload()
相反。
以下功能便于处理 PEP 3147 字节编译文件路径。
3.2 新版功能.
- imp.cache_from_source(path, debug_override=None)¶
返回 PEP 3147 与源关联的字节编译文件的路径 path . 例如,如果 path 是
/foo/bar/baz.py
返回值为/foo/bar/__pycache__/baz.cpython-32.pyc
对于python 3.2。这个cpython-32
字符串来自当前的magic标记(请参见get_tag()
如果sys.implementation.cache_tag
则未定义NotImplementedError
将被引发)。通过在True
或False
对于 debug_override 您可以覆盖系统的值__debug__
,导致字节码优化。path 不需要存在。
在 3.3 版更改: 如果
sys.implementation.cache_tag
是None
然后NotImplementedError
提高了。3.4 版后已移除: 使用
importlib.util.cache_from_source()
相反。在 3.5 版更改: 这个 debug_override 参数不再创建
.pyo
文件。
- imp.source_from_cache(path)¶
鉴于 path 到A PEP 3147 文件名,返回关联的源代码文件路径。例如,如果 path 是
/foo/bar/__pycache__/baz.cpython-32.pyc
返回的路径将是/foo/bar/baz.py
. path 但是,如果它不符合 PEP 3147 格式,AValueError
提高了。如果sys.implementation.cache_tag
未定义,NotImplementedError
提高了。在 3.3 版更改: 提高
NotImplementedError
什么时候?sys.implementation.cache_tag
未定义。3.4 版后已移除: 使用
importlib.util.source_from_cache()
相反。
- imp.get_tag()¶
返回 PEP 3147 与此版本的python的magic编号匹配的magic标记字符串,由返回
get_magic()
.3.4 版后已移除: 使用
sys.implementation.cache_tag
直接从python 3.3开始。
以下功能有助于与导入系统的内部锁定机制进行交互。导入的锁定语义是一个实现细节,可能随发布而变化。但是,python确保循环导入在没有任何死锁的情况下工作。
- imp.lock_held()¶
返回
True
如果当前持有全局导入锁,则为False
. 在没有线程的平台上,始终返回False
.在具有线程的平台上,执行导入的线程首先持有全局导入锁,然后为导入的其余部分设置每个模块锁。这会阻止其他线程在原始导入完成之前导入同一个模块,从而防止其他线程看到原始线程构造的不完整模块对象。循环导入是一个例外,通过构造,循环导入必须在某个点公开不完整的模块对象。
在 3.3 版更改: 大多数情况下,锁定方案已更改为每个模块锁定。对于某些关键任务(如初始化每个模块的锁),保留全局导入锁。
3.4 版后已移除.
- imp.acquire_lock()¶
获取当前线程的解释器全局导入锁。导入钩子应该使用这个锁,以确保导入模块时线程的安全。
一旦一个线程获得了导入锁,同一个线程就可以在不阻塞的情况下再次获取它;该线程必须在每次获取它时释放它一次。
在没有线程的平台上,此函数不起任何作用。
在 3.3 版更改: 大多数情况下,锁定方案已更改为每个模块锁定。对于某些关键任务(如初始化每个模块的锁),保留全局导入锁。
3.4 版后已移除.
- imp.release_lock()¶
释放解释器的全局导入锁。在没有线程的平台上,此函数不起任何作用。
在 3.3 版更改: 大多数情况下,锁定方案已更改为每个模块锁定。对于某些关键任务(如初始化每个模块的锁),保留全局导入锁。
3.4 版后已移除.
此模块中定义的具有整数值的以下常量用于指示 find_module()
.
- imp.PY_SOURCE¶
已将该模块作为源文件找到。
3.3 版后已移除.
- imp.PY_COMPILED¶
该模块被发现为已编译的代码对象文件。
3.3 版后已移除.
- imp.C_EXTENSION¶
该模块被发现为动态可加载的共享库。
3.3 版后已移除.
- imp.PKG_DIRECTORY¶
模块被作为包目录找到。
3.3 版后已移除.
- imp.C_BUILTIN¶
该模块是作为内置模块找到的。
3.3 版后已移除.
- imp.PY_FROZEN¶
该模块被发现为冻结模块。
3.3 版后已移除.
- class imp.NullImporter(path_string)¶
这个
NullImporter
类型是 PEP 302 导入通过找不到任何模块来处理非目录路径字符串的挂钩。使用现有目录或空字符串调用此类型将引发ImportError
. 否则,ANullImporter
返回实例。实例只有一个方法:
- find_module(fullname[, path])¶
此方法始终返回
None
,表示找不到请求的模块。
在 3.3 版更改:
None
插入到sys.path_importer_cache
而不是NullImporter
.3.4 版后已移除: 插入
None
进入之内sys.path_importer_cache
相反。
实例¶
下面的函数模拟到python 1.4之前的标准导入语句(没有层次模块名)。(这个 实施 在那个版本中不起作用,因为 find_module()
已延期 load_module()
已在1.4)中添加:
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()