在 import 语句上使用 importlib.import_module

Using importlib.import_module over an import statement

我使用的是 api -- smartsheet-python-sdk 从源代码执行时 运行 没问题。但是,当我使用 PyInstaller 打包时出现错误,因为 PyInstaller 找不到必要的模块。在 smartsheet 库中,它使用 importlib.import_module 从库中导入模块。

    def __getattr__(self, name):
        """
        Handle sub-class instantiation.

        Args:
            name (str): Name of smartsheet to instantiate.

        Returns:
            Instance of named class.
        """
        try:
            # api class first
            class_ = getattr(importlib.import_module(
                __package__ + '.' + name.lower()), name)
            return class_(self)
        except ImportError:
            # model class next:
            try:
                class_ = getattr(importlib.import_module(
                    name.lower()), name)
                return class_()
            except ImportError:
                self._log.error(
                    'ImportError! Could not load api or model class %s', name)
                return name

当它只从自己的库中导入模块而不是只向已知模块添加导入语句时,使用这样的东西有什么objective好处吗?

从实际的角度来看,有几个不同的原因可以解释为什么这种方法是有利的。

方便

明确列出模块需要额外的步骤,必须执行这些步骤才能集成新模块。可以完全省略声明导入的这一步。

不易出错

如果不经常添加新模块,忘记将模块导入到正确的位置是可能发生的简单小错误之一。删除该要求意味着不会发生错误。这种方法会有其他缺点吗?当然可以,但这些权衡的权重是主观的。

可扩展性

在您写的评论中

I just don't see the reason this particular case would need that since it will only ever be referring to its own modules.

这是一个错误的假设。一个模块完全有可能在未来的某个时间点来自另一个位置。不太可能?也许吧,但这种设计允许更容易地添加一个新的可能位置——这里使用了两个位置,第三个当然是可能的。例如,模拟可能用于测试目的。当然还有其他可行的方法,但这似乎是这种方法的一个可能原因。

但是 PyInstaller 呢?

最终,您是对的,这种方法很难轻松加载到 PyInstaller 中。从 their documentation 开始,您可以将一些解决方法应用于构建过程的脚本。 (为了方便复制在这里)

Some Python scripts import modules in ways that PyInstaller cannot detect: for example, by using the __import__() function with variable data, using imp.find_module(), or manipulating the sys.path value at run time. If your script requires files that PyInstaller does not know about, you must help it:

  • You can give additional files on the pyinstaller command line.
  • You can give additional import paths on the command line.
  • You can edit the myscript.spec file that PyInstaller writes the first time you run it for your script. In the spec file you can tell PyInstaller about code modules that are unique to your script.
  • You can write “hook” files that inform PyInstaller of hidden imports. If you create a “hook” for a package that other users might also use, you can contribute your hook file to PyInstaller.