首页 > 编程问答 >让 cpython 优化恒定条件

让 cpython 优化恒定条件

时间:2024-07-20 23:33:42浏览次数:13  
标签:python debugging optimization

我正在用 Python 编写需要尽可能高效运行的代码,但有时我需要深入挖掘调试语句。不要注释这些输入或输出(或者使用外部预处理器来处理代码,就像这里建议的那样 Python 相当于#ifdef DEBUG 或这里 如何在 python 中实现“#ifdef”?| ||) 我想在模块的开头定义一个变量 如果需要的话我可以轻松地从 False 更改为 True。然后,我的日志记录代码如下所示:

_verbose_debugging = False

但是,我想要的是,如果它设置为“False”,则在生成的字节码中完全省略调试,类似于

if _verbose_debugging:
    print("something resource intensive")

功能。但是,我确实 __debug__ 不想 想要使用 ,因为它默认打开并且会导致其他冲突。 __debug__ 有没有办法告诉CPython字节码编译器我的变量

永远不会在解释器运行时发生变化,如果它曾经见过 _verbose_debugging 那里一次,它可以安全地优化它? False 我读了很多Stackoverflow文章并研究了

的内部行为(不幸的是,这似乎是“神奇的”) ”)。 __debug__ (which unfortunately seems to be "magic").


你不能完全做你想做的事。 CPython 编译器不会对可以在运行时更改的变量进行假设。

但是,你可以实现类似的目标,有一些缺点:

1. 使用函数

你可以把你的调试代码放在一个函数里,然后根据 _verbose_debugging 的值调用这个函数:

_verbose_debugging = False

def debug_print(message):
  if _verbose_debugging:
    print(message)

# ... 你的代码 ...

debug_print("something resource intensive") 

如果 _verbose_debugging False ,这个方法仍然会产生函数调用的开销,但这比原始代码要小得多。

2. 使用 ast 模块进行预处理

你可以使用 Python 的 ast 模块编写一个预处理器,在编译时删除调试代码。 这个方法更复杂,但可以完全消除运行时开销。

这是一个简单的例子:

import ast

class RemoveDebugging(ast.NodeTransformer):
  def visit_Call(self, node):
    if isinstance(node.func, ast.Name) and node.func.id == 'debug_print':
      return ast.Constant(value=None)
    return node

code = """
_verbose_debugging = False

def debug_print(message):
  if _verbose_debugging:
    print(message)

debug_print("This will be removed")
"""

tree = ast.parse(code)
transformer = RemoveDebugging()
transformer.visit(tree)
ast.fix_missing_locations(tree)
compiled_code = compile(tree, '<string>', 'exec')
exec(compiled_code)

在这个例子中, RemoveDebugging 类会找到所有对 debug_print 的调用,并将它们替换成 None

重要的是要注意 ,这些方法仍然依赖于在代码中设置 _verbose_debugging 的值。 它们不会在字节码级别神奇地优化代码。

总的来说,虽然你不能完全复制 C 风格的 #ifdef 行为,但你可以使用这些技术最小化调试代码的性能影响。 选择最适合你的项目的那个。

标签:python,debugging,optimization
From: 78773168

相关文章

  • 如何使用 for 循环在 python jupyter 笔记本中创建动态图?
    我正在学习本课关于用Python求解热方程。该课程指出,在求解热方程后,我们可以通过在循环中简单地调用pyplot.plot()来可视化解的动画图,其中下面的代码将动态绘制每次每个点的温度,从而得到一个动画情节(课程帖子中提供了动画情节的示例)。importnumpyfrommatplotlibi......
  • Python:动态爱心代码
    importrandomfrommathimportsin,cos,pi,logfromtkinterimport*CANVAS_WIDTH=640CANVAS_HEIGHT=480CANVAS_CENTER_X=CANVAS_WIDTH/2CANVAS_CENTER_Y=CANVAS_HEIGHT/2IMAGE_ENLARGE=11HEART_COLOR="#FF99CC"defcenter_......
  • 如何在 PYTHON 中查找输入数字的千位、百位、十位和个位中的数字?例如:256 有 6 个一、5
    num=int(input("Pleasegivemeanumber:"))print(num)thou=int((num//1000))print(thou)hun=int((num//100))print(hun)ten=int((num//10))print(ten)one=int((num//1))print(one)我尝试过这个,但它不起作用,我被困住了。代码几乎是正确的,但需......
  • ModuleNotFoundError:没有名为“pyaes”的模块 python 虚拟机
    在此处输入图像描述当我在启动python项目的虚拟机上构建某个工具时,几秒钟后会出现此消息。我已经尝试重新安装pyaes但无济于事。谁能帮我?非常感谢我已经尝试重新安装pyaes但无济于事,我搜索了tepyaes模块的十个路径,但我没有找到它,而我在另一台虚拟机上完成了......
  • 如何通过 mutagen (Python) 为 mp3 文件中的情绪添加价值?
    我找不到通过mutagen(Python库)将情绪写入mp3文件的方法初始化:frommutagen.mp3importMP3frommutagen.id3importID3,TIT2,TALB,TPE1,TPE2,TCON,TPUB,TENC,TIT3,APIC,WOAR,PRIVaudio=MP3(mp3_file,ID3=ID3)我可以使用audio['TIT3']=TIT3(......
  • 使用 Python 操作 Splunk
    使用Python操作Splunk目录使用Python操作Splunk1参考文档2安装PythonSplunk-SDK3连接splunk4配置查询5参考1参考文档SplunkGithub地址:GitHub-splunk/splunk-sdk-python:SplunkSoftwareDevelopmentKitforPythonSplunk开发者文档地址:Pythontools|......
  • Python:如何通过请求帖子对评论进行投票?
    我对评论进行投票的代码无法正常工作。它返回一个http500错误。我有一个使用用户登录的Python程序,它应该自动对评论进行投票。我的代码如下:frombs4importBeautifulSoupimportrequestslogin_url="https://xxxxxxxxxxx/auth/login"login_url_post="http......
  • python_day7(补1)
    数据类型​ 之前为列表类型​ 插入一个元组的介绍 之后还有字典,三者区别为括号方式()[]{}元组类型(tuple)使用:先定义一个元组数据​ vegetable_tuple='(tomato','corn','cucumber','carrot','corn','pumpkin)'与列表类型格式很像,不过只能取不能改,需要特......
  • 在 python 中写入 %appdata% 时出现奇怪的行为
    我试图将一些数据写入%appdata%。一切似乎都像Script1的输出中所示的那样工作。正在创建新目录并保存文件,并且也成功检索数据。但尝试查看文件资源管理器中的数据时,该文件夹不存在!CMD也找不到文件和目录。后来我手动创建了文件,检查了一下,发生了什么。CMD现在可以找到该文......
  • 使用 selenium 在 python 中打开 chrome 中的链接
    通过此链接https://bancadatistatisticaoas.inail.it/analytics/saw.dll?Dashboard&PortalPath=%2Fshared%2FBDS%2F_portal%2FINF_Definiti_Industria_e_Servizi我需要单击“FCostruzioni”,然后单击F41COSTRUZIONIED埃迪菲西。这是我的代码,但它不起作用。我做错了......