【问题标题】:Activating Python's optimization mode via script-level command-line argument通过脚本级命令行参数激活 Python 的优化模式
【发布时间】:2015-04-04 20:20:09
【问题描述】:

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

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

我知道__debug__不能在运行时设置;它作为不可变常量在语言中被特例化。但是,主脚本中没有任何有问题的断言语句,我可以很容易地延迟加载我的其他模块,直到我完成命令行参数的解析。因此,如果有某种方法可以从 Python 中设置 -O 标志,或者有某种带有标志的导入功能,那就可以了。

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

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

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

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

【问题讨论】:

    标签: python optimization


    【解决方案1】:

    如果设置了__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 告诉您设置了哪些布尔选项,但它没有告诉您有关-m 参数的信息。我认为这本身很有趣,所以在这里创建了一个单独的问题:Retrieve the command line arguments of the Python interpreter

    【讨论】:

      猜你喜欢
      • 2019-08-25
      • 2014-04-03
      • 2014-07-31
      • 2014-05-11
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多