python - 从 imp 到 importlib 的过渡

标签 python python-3.x

我想使用的项目有部分代码

_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) 检查

  1. 我们意识到 imp.get_magic() 可以替换为 importlib.util.MAGIC_NUMBER

  2. 然后我们检查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_SOURCEimp.PY_COMPILEDimp.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/

相关文章:

python - 在索引数组中获取最小值

python - 如何测试对象是否是一个映射(支持**O用法)

python - 对列表中的数组求和

python-3.x - Python Pandas - 根据单元格值查找列值

python-3.x - 在 Python 3 中未显式打开文件时处理从字节到字符串的转换

python - 从列表的元素中查找互斥集的 python 组合

python - 在运行时更改上传路径 (UPLOAD_FOLDER)

python - except block 未捕获 Cloud firestore 异常

python-3.x - Pandas:基于多列对数据框进行排序

python - Pygame 使用 PyTMX 加载 Tilemap