我想使用的项目有部分代码
_VALID_MODULE_TYPES = set((imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION))
[...]
for suffix, mode, type in imp.get_suffixes():
if type in self._VALID_MODULE_TYPES:
path = prefix + suffix
if self.file_system.isfile(path):
return path, type
[...]
if type == imp.PY_SOURCE:
code = self.file_system.readbytes(path).replace(b("\r\n"), b("\n"))
return compile(code, path, "exec")
elif type == imp.PY_COMPILED:
code = self.file_system.readbytes(path)
if code[:4] != imp.get_magic():
return None
return marshal.loads(code[8:])
elif type == imp.C_EXTENSION:
code = self.file_system.readbytes(path)
使用模块imp
。据说 imp
已被弃用,应该使用 importlib
代替,但我不知道如何过渡。我该如何重写代码?
最佳答案
1) 检查
我们意识到
imp.get_magic()
可以替换为importlib.util.MAGIC_NUMBER
。然后我们检查
imp.get_suffixes
def get_suffixes():
"""**DEPRECATED**"""
extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES]
source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
return extensions + source + bytecode
我们注意到
get_suffixes
使用一些“魔数(Magic Number)”imp.PY_SOURCE
、imp.PY_COMPILED
、imp.C_EXTENSION
get_suffixes
使用来自importlib
的
machinery
2) 重构以独立于 imp
我们重写了之前的代码。我们进一步改进它
- 使用
枚举
- 在最后一个 block 中使用
is
而不是==
import importlib.machinery
class ModuleType(Enum):
SEARCH_ERROR = 0
PY_SOURCE = 1
PY_COMPILED = 2
C_EXTENSION = 3
PY_RESOURCE = 4
PKG_DIRECTORY = 5
C_BUILTIN = 6
PY_FROZEN = 7
PY_CODERESOURCE = 8
IMP_HOOK = 9
# _VALID_MODULE_TYPES = {ModuleType.PY_SOURCE, ModuleType.PY_COMPILED}
_VALID_MODULE_TYPES = {ModuleType.PY_SOURCE, ModuleType.PY_COMPILED, ModuleType.C_EXTENSION}
def get_suffixes():
extensions = [(s, 'rb', C_EXTENSION) for s in importlib.machinery.EXTENSION_SUFFIXES]
source = [(s, 'r', PY_SOURCE) for s in importlib.machinery.SOURCE_SUFFIXES]
bytecode = [(s, 'rb', PY_COMPILED) for s in importlib.machinery.BYTECODE_SUFFIXES]
return extensions + source + bytecode
[...]
for suffix, mode, type in get_suffixes():
if type in _VALID_MODULE_TYPES:
path = prefix + suffix
if self.file_system.isfile(path):
return path, type
[...]
if type is PY_SOURCE:
code = self.file_system.readbytes(path).replace(b("\r\n"), b("\n"))
return compile(code, path, "exec")
elif type is PY_COMPILED:
code = self.file_system.readbytes(path)
if code[:4] != importlib.util.MAGIC_NUMBER:
return None
return marshal.loads(code[8:])
elif type is C_EXTENSION:
code = self.file_system.readbytes(path)
3) 进一步重构
我们还可以通过写进一步重构
_VALID_MODULE_TYPES = [ModuleType.PY_SOURCE, ModuleType.PY_COMPILED, ModuleType.C_EXTENSION]
def get_suffixes(return_as_dict=False):
if return_as_dict:
suffixes = {
ModuleType.C_EXTENSION: (importlib.machinery.EXTENSION_SUFFIXES, 'rb'),
ModuleType.PY_SOURCE: (importlib.machinery.SOURCE_SUFFIXES, 'r'),
ModuleType.PY_COMPILED: (importlib.machinery.BYTECODE_SUFFIXES, 'rb')
}
else:
extensions = [(s, 'rb', ModuleType.C_EXTENSION) for s in importlib.machinery.EXTENSION_SUFFIXES]
source = [(s, 'r', ModuleType.PY_SOURCE) for s in importlib.machinery.SOURCE_SUFFIXES]
bytecode = [(s, 'rb', ModuleType.PY_COMPILED) for s in importlib.machinery.BYTECODE_SUFFIXES]
suffixes = extensions + source + bytecode
return suffixes
这样我们就可以设置我们希望通过 _VALID_MODULE_TYPES
的顺序,并且我们还可以通过减少迭代来改进
suffixes = get_suffixes(return_as_dict=True)
for module_type in _VALID_MODULE_TYPES:
for suffix in suffixes[module_type][0]:
path = prefix + suffix
if self.file_system.isfile(path):
return path, module_type
return None, None
关于python - 从 imp 到 importlib 的过渡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61622881/