如何以可读的方式级联尝试导入

How to cascade try imports in a readable way

我想尝试在 python 中导入一个 JSON 解析库列表,项目的优先顺序是它们被尝试的顺序。如果我有以下 json 库 ajsonbjson,...我必须写类似

的内容
try:
    import ajson as json
except ImportError:
    try:
        import bjson as json
    except ImportError:
        try:
            import cjson as json
        except ImportError:
            ...

这是非常不可读的。有没有更好的方法来像 if 语句那样做?

您可以使用 importlib

遍历要导入的库
import importlib
libs = ["os", "sys", "json"]
for lib in libs:
    try:
        globals()[lib] = importlib.import_module(lib)
        break #if you don't want to keep importing once you imported a library successfully
    except:
        pass

这似乎有效:

for lib in ['ajson','bjson','cjson']:
    try:
        __import__(lib)
        print('Imported ' + lib)
        break
    except ImportError:
        continue

您可以定义一个封装此回退行为的函数:

import importlib

def import_fallback(*modules):
  for m in modules:
    try:
      return importlib.import_module(m)
    except ImportError:
      continue
  raise ImportError("All fallback imports failed: {}".format(modules))

# You can use it like this
json = import_fallback("ajson", "bjson", "cjson")

编辑:这样做可能有不利之处。某些 linter 或静态代码分析器可能不知道您正在通过 运行 此函数

导入这些模块

无需使用 tryexcept 产生异常并捕获它们,您可以使用 importlib.util.find_spec 函数简单地过滤模块名称,returns None 如果没有找到给定的模块名称,然后使用 importlib.import_module:

导入找到的模块
json = importlib.import_module(
    next(filter(importlib.util.find_spec, ("ajson", "bjson", "cjson")))
)