通过脚本级命令行参数激活Python的优化模式 [英] Activating Python's optimization mode via script-level command-line argument

查看:129
本文介绍了通过脚本级命令行参数激活Python的优化模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个脚本,可以加载各种模块来完成其工作.其中的某些模块沉重中充斥有assert语句-足以潜在地导致实际使用中的速度显着下降. (我正在做很多涉及变异图的操作,因此有很多断言可以遍历整个图以强制执行不变式或检查结果的正确性.)因此,我想允许用户在以下情况下禁用这些检查:他们希望.似乎很简单;这正是-O标志的功能,对吧?

I have a script which loads various modules to do its job. Some of these modules are heavily studded with assert statements - enough to potentially cause significant slow-downs in actual use. (I'm doing a lot of operations which involve mutating graphs, so there are lots of asserts which iterate over the entire graph in order to enforce invariants or check the correctness of results.) So I want to allow users to disable these checks if they wish. Seems simple enough; this is exactly what the -O flag does, right?

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

However, the problem is that -O is a flag handled by the Python interpreter. I don't want to force my users to explicitly call the interpreter just to access this functionality - I want to support MyScript.py -O, rather than python -O MyScript.py. Is there any way I can do this?

我知道__debug__不能在运行时设置;它在语言中是特殊的,是不变的常量.但是,主脚本中没有任何有问题的assert语句,并且我可以轻松地将其他模块的加载延迟到完成对命令行参数的解析之后.因此,如果有某种方法可以从Python内部设置-O标志,也可以使用某种带有标志的import-with-flags功能,那么就可以做到.

I know that __debug__ cannot be set at run-time; it is special-cased into the language as an immutable constant. However, none of the problematic assert statements are in the main script, and I could easily delay loading my other modules until after I've finished parsing the command-line arguments. So if there's either some way to set the -O flag from within Python or some sort of import-with-flags functionality, that would do it.

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

Note 1: To be clear, it is not sufficient just to disable assert statements; there are also pieces of code which are conditional on the __debug__ constant (e.g. if (__debug__): for x in large_expensive_set: assert some_property_of(x)) which needs to not be executed.

注2:另一方面,我不关心代码的内存大小,而只关心速度,而我的速度关心是基于assert语句中昂贵的函数和debug-only代码中昂贵的循环.我知道Python的代码生成器在-O模式下运行时会忽略已编译代码中的assert语句和if (__debug__):块,但是如果没有发生就可以了-我不介意debug-only语句是否 present ,只要它们不执行即可.

Note 2: On the other hand, I'm not concerned about code memory size, only speed, and my speed concerns are based around expensive functions in assert statements and expensive loops in debug-only code. I know that Python's code generator, when running in -O mode, omits assert statements and if (__debug__): blocks from the compiled code, but it's fine if that doesn't happen - I don't mind if the debug-only statements are present, as long as they don't execute.

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

Note 3: I've considered just passing around a manual debug flag and replacing all the asserts with if (self.__debug and not assert_condition): raise AssertionError(). However, that solution:

  • 可读性极差
  • 效率低很多
  • 需要更改很多代码
  • 需要非平凡的重构(每个对象都必须带有调试标志,将其存储并传递给它产生的每个子对象)

推荐答案

如果设置了__debug__,则只需重新启动即可.在脚本顶部,尝试以下操作:

You can simply relaunch yourself if __debug__ is set. At the top of your script, try this:

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

这将使用python -O用新进程替换正在运行的进程.请注意,os.execv永远不会返回-确实会替换正在运行的进程.

This replaces the running process with a new one using python -O. Note that os.execv never returns--it really does replace the running process.

这种方法的一个怪癖是它不保留Python解释器的选项,因此,如果您运行python -m cProfile myscript,它将在没有cProfile的情况下重新启动.我不确定如何解决此问题... sys.flags 告诉您设置了哪些布尔选项,但不会告诉您-m参数.我认为这本身很有趣,因此在这里创建了一个单独的问题:

One quirk of this approach is that it does not preserve options to the Python interpreter, so if you run python -m cProfile myscript it will relaunch without cProfile. I'm not sure how to fix this...sys.flags tells you which boolean options were set, but it doesn't tell you about -m arguments. I thought this was interesting by itself, so created a separate question about it here: Retrieve the command line arguments of the Python interpreter

这篇关于通过脚本级命令行参数激活Python的优化模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆