我有一个脚本,它加载各种模块以完成其工作。其中一些模块含有大量的assert语句,可能会在实际使用中导致显着的减速。(我正在进行许多涉及变异图形的操作,因此有很多assert语句迭代整个图形以强制执行不变量或检查结果的正确性。)因此,我希望允许用户在需要时禁用这些检查。看起来很简单;这正是 -O 标志的作用,对吧?
但问题在于 -O 是 Python 解释器处理的标志。我不想强制我的用户显式调用解释器才能访问此功能——我想支持 MyScript.py -O,而不是 python -O MyScript.py。有没有办法可以做到这一点?
我知道__debug__不能在运行时设置;它被特别处理为一个不可变常量。然而,所有有问题的 assert 语句都不在主脚本中,我可以很容易地延迟加载其他模块,直到完成解析命令行参数之后。因此,如果有一种从 Python 中设置 -O 标志的方法或某种带有标志的导入功能,那就可以了。
注意1:要明确的是,仅禁用 assert 语句是不够的;还有一些代码是根据 __debug__ 常量条件执行的(例如 if (__debug__): for x in large_expensive_set: assert some_property_of(x)),这些代码需要被禁用。
注意2:另一方面,我不关心代码内存大小,只关心速度,并且我的速度问题基于 assert 语句中的昂贵函数和仅调试代码中的昂贵循环。我知道 Python 的代码生成器在 -O 模式下运行时会省略 assert 语句和 if (__debug__): 块,但如果不发生这种情况也没关系——我不介意调试专用语句是否存在,只要它们不执行即可。
注意3:我考虑了传递手动调试标志并将所有 assert 替换为 if (self.__debug and not assert_condition): raise AssertionError()。然而,该解决方案:
- 可读性极差 - 效率远低于其他方案 - 需要更改大量代码 - 需要进行非平凡的重构(每个对象都必须带有一个调试标志,存储它,并将其传递给它生成的每个子对象)
但问题在于 -O 是 Python 解释器处理的标志。我不想强制我的用户显式调用解释器才能访问此功能——我想支持 MyScript.py -O,而不是 python -O MyScript.py。有没有办法可以做到这一点?
我知道__debug__不能在运行时设置;它被特别处理为一个不可变常量。然而,所有有问题的 assert 语句都不在主脚本中,我可以很容易地延迟加载其他模块,直到完成解析命令行参数之后。因此,如果有一种从 Python 中设置 -O 标志的方法或某种带有标志的导入功能,那就可以了。
注意1:要明确的是,仅禁用 assert 语句是不够的;还有一些代码是根据 __debug__ 常量条件执行的(例如 if (__debug__): for x in large_expensive_set: assert some_property_of(x)),这些代码需要被禁用。
注意2:另一方面,我不关心代码内存大小,只关心速度,并且我的速度问题基于 assert 语句中的昂贵函数和仅调试代码中的昂贵循环。我知道 Python 的代码生成器在 -O 模式下运行时会省略 assert 语句和 if (__debug__): 块,但如果不发生这种情况也没关系——我不介意调试专用语句是否存在,只要它们不执行即可。
注意3:我考虑了传递手动调试标志并将所有 assert 替换为 if (self.__debug and not assert_condition): raise AssertionError()。然而,该解决方案:
- 可读性极差 - 效率远低于其他方案 - 需要更改大量代码 - 需要进行非平凡的重构(每个对象都必须带有一个调试标志,存储它,并将其传递给它生成的每个子对象)