代码之家  ›  专栏  ›  技术社区  ›  Olivier Melançon iacob

Python3中构建模块异常的最佳实践

  •  6
  • Olivier Melançon iacob  · 技术社区  · 7 年前

    假设我有一个这样的文件夹结构的项目。

    /project
        __init__.py
        main.py
        /__helpers
            __init__.py
            helpers.py
            ...
    

    模块 helpers.py 定义一些异常并包含引发该异常的某些方法。

    # /project/__helpers/helpers.py
    
    class HelperException(Exception):
        pass
    
    def some_function_that_raises():
        raise HelperException
    

    另一方面,我的 main.py 模块定义自己的异常并导入可能引发异常的方法 助手。py公司 .

    # /projects/main.py
    
    from project.__helpers.helpers import some_function_that_raises
    
    class MainException(Exception):
        pass
    

    现在,我不希望用户不得不这样做 from project.__helpers.helpers import HelperException 如果他们想抓住这个例外。如果能够从引发异常的公共模块中导入该异常,将更有意义。

    但我不能动 HelperException 主要的py公司 ,这将创建循环导入。

    允许用户从导入所有异常的最佳方式是什么 主要的py公司 而那些在 /__helpers ?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Olivier Melançon iacob    5 年前

    这是我想出的解决方案。

    其基本思想是将所有异常放在一个文件中,从中可以导入它们,然后将它们全部导入 main.py . 为了使一切都清晰明了,我们最终定义 __all__ 模块的属性。

    这是新的文件结构

    /project
        __init__.py
        main.py
        /__helpers
            __init__.py
            exceptions.py
            helpers.py
            ...
    

    这是 exceptions.py 文件

    # /project/__helpers/exceptions.py
    
    class MainException(Exception):
        pass
    
    # Note that this also allows us to inherit between exceptions
    class HelperException(MainException):
        pass
    

    然后,我们可以从该文件导入异常,而不存在循环依赖的风险。

    最后我们定义 __全部__ 在里面 主要的py公司 明确要导入异常。

    # /projects/main.py
    
    from project.__helpers.helpers import some_function_that_raises
    from project.__helpers.exceptions import MainException, HelperException
    
    __all__ = ['MainException', 'HelperException', ...]
    

    只是提醒一下 __全部__ 属性定义了要执行的操作将导入的内容 from project import * . 因此,这将期望的行为扩展到 import star 并明确表示我们希望从该文件导入异常。

    还请注意,一些IDE甚至会 'HelperException' 正在加入 __全部__ 作为参考 HelperException 并且不会因为有一个未使用的导入而困扰您。这就是为什么我认为这是正确的方法。