36.2. imp
- 访问import内部¶
源代码: Lib / imp.py
此模块提供了用于实现import
语句的机制的接口。它定义了以下常量和函数:
-
imp.
get_magic
()¶ 返回用于识别字节编译代码文件(
.pyc
文件)的魔术字符串值。(每个Python版本的此值可能不同。)自版本3.4后已弃用:改用
importlib.util.MAGIC_NUMBER
。
-
imp.
get_suffixes
()¶ 返回一个3元素元组的列表,每个元组描述特定类型的模块。每个三元组具有
(后缀, 模式, 类型)
的形式,其中是要附加到模块名称以形成要搜索的文件名的字符串,模式是要传递到内建open()
函数的模式字符串,文件(对于文本文件可以是'r'
,对于二进制文件可以是'rb'
),类型是文件类型,以下描述的值PY_SOURCE
,PY_COMPILED
或C_EXTENSION
中的一个。自版本3.3后已弃用:改用
importlib.machinery
中定义的常量。
-
imp.
find_module
(name[, path])¶ 尝试找到名称。如果省略path或
None
,将搜索由sys.path
给出的目录名称列表,但首先搜索几个特殊位置:该函数尝试查找具有给定名称(C_BUILTIN
),冻结模块(PY_FROZEN
)的内建模块,在某些系统上,一些其他地方被查找(在Windows上,它注册表中可能指向一个特定的文件)。否则,路径必须是目录名称列表;将搜索每个目录中具有由上述
get_suffixes()
返回的任何后缀的文件。列表中无效的名称将被忽略(但所有列表项必须是字符串)。如果搜索成功,返回值为3元素元组
(文件, 路径名, 描述)
文件是位于开头的开放file object,路径名是找到的文件的路径名,描述是由
get_suffixes()
返回的列表中包含的描述所找到的模块类型的3元素元组。如果模块不在文件中,返回的文件为
None
,路径名为空字符串,/ t4> tuple包含其后缀和模式的空字符串;模块类型如上面括号中所示。如果搜索不成功,则会引发ImportError
。其他异常表示参数或环境的问题。如果模块是包,文件是
None
,路径名是包路径和描述 t4中的最后一个项目> tuple是PKG_DIRECTORY
。此函数不处理分层模块名称(包含点的名称)。为了找到PM,即包裹P的子模块M,请使用
find_module()
和load_module()
找到并加载包P,然后使用find_module()
,将路径参数设置为P.__path__
。当P本身有点名时,以递归方式应用此配方。自版本3.3后已弃用:除非需要Python 3.3兼容性,否则使用
importlib.util.find_spec()
,在这种情况下,请使用importlib.find_loader()
-
imp.
load_module
(name, file, pathname, description)¶ 加载以前由
find_module()
发现的模块(或通过其他方式进行的搜索,产生兼容的结果)。此函数不仅仅导入模块:如果模块已经导入,它将重新加载模块!name参数指示完整的模块名称(包括程序包名称,如果它是程序包的子模块)。文件参数是打开的文件,路径名是相应的文件名;当模块是包或者没有从文件加载时,这些可以分别是None
和''
。描述参数是一个元组,由get_suffixes()
返回,描述必须加载什么样的模块。如果加载成功,返回值是模块对象;否则,引发异常(通常
ImportError
)。重要提示:如果不是
None
,即使发生异常,调用者也负责关闭文件参数。最好使用try
...finally
语句。Deprecated since version 3.3: If previously used in conjunction with
imp.find_module()
then consider usingimportlib.import_module()
, otherwise use the loader returned by the replacement you chose forimp.find_module()
. 如果您直接调用imp.load_module()
和相关函数,请使用importlib.machinery
中的类,例如importlib.machinery.SourceFileLoader(name, path).load_module()
。
-
imp.
new_module
(name)¶ 返回一个名为name的新模块对象。此对象不是插入到
sys.modules
中。自版本3.4后已弃用:改用
types.ModuleType
。
-
imp.
reload
(module)¶ 重新载入先前导入的模块。参数必须是一个模块对象,因此必须先被成功导入。如果您已使用外部编辑器编辑了模块源文件,并希望在不离开Python解释器的情况下尝试新版本,这将非常有用。返回值是模块对象(与模块参数相同)。
当执行
reload(module)
时:- Python模块的代码被重新编译并重新执行模块级代码,定义一组新的对象,这些对象绑定到模块字典中的名称。扩展模块的
init
功能不再第二次调用。 - 与Python中的所有其他对象一样,旧对象只有在引用计数下降到零后才被回收。
- 模块命名空间中的名称将更新为指向任何新的或已更改的对象。
- 对旧对象的其他引用(例如模块外部的名称)不会重新引用来引用新对象,如果需要,必须在每个命名空间中对其进行更新。
还有一些其他警告:
重新加载模块时,将保留其字典(包含模块的全局变量)。名称的重定义将覆盖旧的定义,因此这通常不是问题。如果模块的新版本未定义由旧版本定义的名称,则旧定义将保留。如果它维护一个全局表或对象缓存,使用
try
语句可以测试表的存在并跳过其初始化,如果需要,这个特性可以用于模块的优势:try: cache except NameError: cache = {}
除了
sys
,__main__
和builtins
除外,重新加载内建或动态加载的模块通常不太有用。然而,在许多情况下,扩展模块不被设计为被不止一次地初始化,并且可以在被重新加载时以任意方式失败。如果模块使用
from
...import
...从另一个模块导入对象,则对其他模块调用reload()
其中一个方法是重新执行from
语句,另一个是使用import
和限定名称(module 。* name *)。如果一个模块实例化一个类的实例,重新加载定义该类的模块不会影响实例的方法定义 - 它们继续使用旧的类定义。对于派生类同样如此。
在版本3.3中更改:依赖于正在重新加载的模块上定义的
__name__
和__loader__
,而不仅仅是__name__
。自版本3.4后已弃用:改用
importlib.reload()
。- Python模块的代码被重新编译并重新执行模块级代码,定义一组新的对象,这些对象绑定到模块字典中的名称。扩展模块的
以下函数是处理 PEP 3147字节编译的文件路径的便利。
版本3.2中的新功能。
-
imp.
cache_from_source
(path, debug_override=None)¶ 将 PEP 3147路径返回到与源路径相关联的字节编译文件。例如,如果path是
/foo/bar/baz.py
,则返回值为/foo/bar/__pycache__/baz.cpython-32.pyc
for Python 3.2。Thecpython-32
string comes from the current magic tag (seeget_tag()
; ifsys.implementation.cache_tag
is not defined thenNotImplementedError
will be raised). 通过为debug_override传递True
或False
,您可以覆盖__debug__
的系统值,从而导致优化的字节码。路径不需要存在。
在版本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)¶ 给定路径到 PEP 3147文件名,返回关联的源代码文件路径。例如,如果路径为
/foo/bar/__pycache__/baz.cpython-32.pyc
,则返回的路径为/foo/bar/baz.py
。path不需要存在,但如果它不符合 PEP 3147格式,则会引发ValueError
。如果未定义sys.implementation.cache_tag
,则会引发NotImplementedError
。在未定义
sys.implementation.cache_tag
时,在版本3.3中更改了提升NotImplementedError
:自从版本3.4开始弃用:改为使用
importlib.util.source_from_cache()
。
-
imp.
get_tag
()¶ 返回与
get_magic()
返回的Python的幻数的版本匹配的 PEP 3147魔术标记字符串。自版本3.4后弃用:直接从Python 3.3开始使用
sys.implementation.cache_tag
。
以下功能有助于与导入系统的内部锁定机制交互。导入的锁定语义是一个实现细节,它可能因版本而异。然而,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
。否则,将返回NullImporter
实例。实例只有一个方法:
-
find_module
(fullname[, path])¶ 此方法始终返回
None
,表示找不到请求的模块。
在版本3.3中更改:
None
已插入到sys.path_importer_cache
中,而不是NullImporter
的实例。自版本3.4后弃用:改为将
None
插入sys.path_importer_cache
。-
36.2.1. Examples¶
以下函数模拟了直到Python 1.4的标准import语句(没有分层模块名称)。(由于find_module()
已经扩展,并且在1.4中添加了load_module()
,因此此实现
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()