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

通过ctypes复制生成器:解决访问冲突及生成器类型转换问题

生成器复制:解决访问冲突与类型转换问题

我尝试通过传入frame对象调用PyGen_New来复制生成器,最初遇到以下访问冲突错误:

Traceback (most recent call last):
  File "C:\test.py", line 19, in <module>
    frame = Frame(gen.gi_code)
            ^^^^^^^^^^^^^^^^^^
  File "C:\test.py", line 11, in Frame
    return ctypes.pythonapi.PyFrame_New(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: exception: access violation reading 0x0000000000000008

初始使用的代码:

from types import CodeType, FrameType
import ctypes


ctypes.pythonapi.PyThreadState_Get.argtypes = None
ctypes.pythonapi.PyThreadState_Get.restype = ctypes.POINTER(ctypes.c_ulong)
ctypes.pythonapi.PyFrame_New.restype = ctypes.POINTER(ctypes.py_object)

def Frame(code_obj: CodeType, globals: dict = None, locals: dict = None) -> FrameType:
    """Instantiates a FrameType object"""
    return ctypes.pythonapi.PyFrame_New(
        ctypes.pythonapi.PyThreadState_Get(),
        ctypes.cast(id(code_obj), ctypes.POINTER(ctypes.c_int)),
        globals,
        locals,
    )

gen = (i for i in range(3))
frame = Frame(gen.gi_code)

ctypes.pythonapi.PyGen_New.restype = ctypes.POINTER(ctypes.py_object)
new_gen = ctypes.pythonapi.PyGen_New(
    ctypes.cast(id(frame), ctypes.POINTER(ctypes.c_void_p))
)

for value in new_gen:
    print(value)

注:已知CPython未设计支持生成器复制与序列化,无需告知相关风险;本次聚焦解决当前访问冲突错误及后续生成器类型转换的具体方案,不追求通用适配;知晓这是使用C层实现细节,无需赘述。代码运行于Python 3.11.9版本。

更新:访问冲突已解决,类型转换待处理

下述代码解决了访问冲突错误,但仍需解决如何将结果转换为实际生成器类型的问题:

from types import CodeType, FrameType
import ctypes

ctypes.pythonapi.PyFrame_New.argtypes = (
    ctypes.POINTER(ctypes.c_ulong),
    ctypes.POINTER(ctypes.c_ulong),
    ctypes.py_object,
    ctypes.py_object
)
ctypes.pythonapi.PyFrame_New.restype = ctypes.py_object
ctypes.pythonapi.PyThreadState_Get.argtypes = None
ctypes.pythonapi.PyThreadState_Get.restype = ctypes.POINTER(ctypes.c_ulong)


def Frame(code_obj: CodeType, globals: dict = {}, locals: dict = {}) -> FrameType:
    """Instantiates a FrameType object"""
    return ctypes.pythonapi.PyFrame_New(
        ctypes.pythonapi.PyThreadState_Get(),
        ctypes.cast(id(code_obj), ctypes.POINTER(ctypes.c_ulong)),
        globals,
        locals
    )
gen = (i for i in range(3))
frame = Frame(gen.gi_code)

ctypes.pythonapi.PyGen_New.argtypes = [ctypes.POINTER(ctypes.py_object)]
ctypes.pythonapi.PyGen_New.restype = ctypes.POINTER(ctypes.py_object)


new_gen = ctypes.pythonapi.PyGen_New(
    ctypes.cast(id(frame), ctypes.POINTER(ctypes.py_object))
)

## 以下代码无法运行 ##
for value in new_gen:
    print(value)

内容的提问来源于stack exchange,提问作者Ben Tonks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:49:51