You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.10中如何阻止第三方扩展对象的析构函数运行?

阻止Python对象析构函数执行的解决方案

背景

在Python 3.10程序中,使用了第三方扩展模块提供的非纯Python实现的问题对象。由于第三方代码存在bug,该对象的析构函数运行时会导致程序无限期阻塞(等待永远无法获取的互斥锁)。目前修复该阻塞问题的尝试均未成功,但仍在推进。

问题

如何在Python关闭时,有意阻止某个对象的析构函数被调用?例如,test.py中有以下代码:

class MyClass:
    def __del__(self):
        print("bye")

x = MyClass()

需要确保x的析构函数永远不会运行,“bye”永远不会被打印——无论是程序关闭时还是x超出作用域时?

已尝试方案

  • 在优先执行的析构函数中调用os._exit强制退出,但会导致其他必要的析构函数无法执行,得不偿失。
  • 刻意创建包含该对象的引用循环,但无法绕过循环垃圾回收机制。
  • 尝试通过ctypes调用Py_IncRef增加引用计数,未生效:
import ctypes
incref = ctypes.pythonapi.Py_IncRef
incref.argtypes = [ctypes.py_object]
incref.restype = None
incref(x)

可行解决方案

1. 直接替换/移除对象的__del__方法

对于纯Python对象,直接将其__del__属性设为None即可:

x.__del__ = None

如果是C扩展实现的对象,可通过ctypes调用Python C API的Py_SetFinalizer函数,将对象的终结器设为NULL:

import ctypes

pythonapi = ctypes.PyDLL(None)
Py_SetFinalizer = pythonapi.Py_SetFinalizer
Py_SetFinalizer.argtypes = [ctypes.py_object, ctypes.c_void_p]
Py_SetFinalizer.restype = None

# 移除对象的析构函数
Py_SetFinalizer(x, None)

2. 利用垃圾回收机制冻结对象

使用gc模块的freeze()方法,将当前所有对象标记为不可回收,程序退出时不会触发它们的析构函数:

import gc

# 先执行一次垃圾回收,清理无用对象
gc.collect()
# 冻结现有对象,后续不会被垃圾回收处理
gc.freeze()

注意该操作会影响所有现有对象,适合在程序生命周期后期调用,此时无需再创建需要回收的新对象。

3. 手动保留C层面引用,让对象永不销毁

通过ctypes增加对象的C层面引用计数,再清除所有Python层面的引用,使对象的引用计数始终大于0,垃圾回收器不会触发其析构函数:

import ctypes
import gc

# 增加C层面引用计数
incref = ctypes.pythonapi.Py_IncRef
incref.argtypes = [ctypes.py_object]
incref(x)

# 清除Python层面的所有引用
del x
# 强制触发垃圾回收,此时对象因C层面引用存在不会被销毁
gc.collect()

程序退出时,操作系统会直接回收内存,不会执行Python的析构函数。

内容的提问来源于stack exchange,提问作者Zac B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 01:45:33