通过脚本级命令行参数激活Python的优化模式

2024-03-30

我有一个脚本可以加载各种模块来完成其工作。其中一些模块是heavily布满了断言语句——足以在实际使用中导致显着的速度减慢。 (我正在做很多涉及变异图的操作,因此有很多断言会迭代整个图,以强制不变量或检查结果的正确性。)所以我想允许用户禁用这些检查,如果他们希望。看起来很简单;这正是 -O 标志的作用,对吗?

然而,问题在于 -O 是由 Python 解释器处理的标志。我不想强迫我的用户显式调用解释器只是为了访问此功能 - 我想支持MyScript.py -O, 而不是python -O MyScript.py。我有什么办法可以做到这一点吗?

我知道__debug__无法在运行时设置;它在语言中作为不可变常量进行特殊处理。但是,主脚本中没有任何有问题的断言语句,并且我可以轻松地延迟加载其他模块,直到完成解析命令行参数之后。因此,如果有某种方法可以从 Python 中设置 -O 标志,或者某种 import-with-flags 功能,那就可以了。

注 1:需要明确的是,仅仅禁用断言语句是不够的;还有一些代码片段是有条件的__debug__常数(例如if (__debug__): for x in large_expensive_set: assert some_property_of(x)) 不需要执行。

注 2:另一方面,我不关心代码内存大小,只关心速度,而且我的速度问题是基于断言语句中昂贵的函数和仅调试代码中昂贵的循环。我知道Python的代码生成器在-O模式下运行时会省略assert语句并if (__debug__):编译代码中的块,但如果这没有发生也没关系 - 我不介意调试专用语句是否是present,只要他们不执行。

注 3:我考虑过传递手动调试标志并将所有断言替换为if (self.__debug and not assert_condition): raise AssertionError()。然而,该解决方案:

  • 可读性极差
  • 效率低很多
  • 需要更改大量代码
  • 需要进行重要的重构(每个对象都必须采用调试标志,存储它,并将其传递给它生成的每个子对象)

您可以简单地重新启动自己,如果__debug__已设置。在脚本的顶部,尝试以下操作:

if __debug__:
    import os
    import sys
    os.execv(sys.executable, ['python', '-O'] + sys.argv)

这将使用新的进程替换正在运行的进程python -O。注意os.execv永远不会返回——它确实取代了正在运行的进程。

这种方法的一个怪癖是它不保留 Python 解释器的选项,因此如果您运行python -m cProfile myscript它将重新启动,无需cProfile。我不知道如何解决这个问题......sys.flags https://docs.python.org/2/library/sys.html#sys.flags告诉您设置了哪些布尔选项,但它没有告诉您-m论据。我认为这本身很有趣,所以在这里创建了一个单独的问题:检索Python解释器的命令行参数 https://stackoverflow.com/questions/28336431/retrieve-the-command-line-arguments-of-the-python-interpreter

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过脚本级命令行参数激活Python的优化模式 的相关文章

随机推荐