在使用可调用程序修补原始python类型的__rshift__
运算符时,该修补程序使用了包装器:
def _patch_rshift(py_class, func):
assert isinstance(func, FunctionType)
py_type_name = 'tp_as_number'
py_type_method = 'nb_rshift'
py_obj = PyTypeObject.from_address(id(py_class))
type_ptr = getattr(py_obj, py_type_name)
if not type_ptr:
tp_as_obj = PyNumberMethods()
FUNC_INDIRECTION_REFS[(py_class, '__rshift__')] = tp_as_obj
tp_as_new_ptr = ctypes.cast(ctypes.addressof(tp_as_obj),
ctypes.POINTER(PyNumberMethods))
setattr(py_obj, py_type_name, tp_as_new_ptr)
type_head = type_ptr[0]
c_func_t = binary_func_p
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except BaseException as be:
# Need to raise a python style error here:
wrapper.exc_info = sys.exc_info()
return False
c_func = c_func_t(wrapper)
C_FUNC_CALLBACK_REFS[(py_class, '__rshift__')] = c_func
setattr(type_head, py_type_method, c_func)
现在的挑战是,一旦wrapper
中捕获到异常,就像在普通Python中一样在这里引发异常。
筹集方式:
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except BaseException as be:
raise
还是根本没有抓住:
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
收益:
Windows fatal exception: access violation
Process finished with exit code -1073741819 (0xC0000005)
所需的行为是简单地重新引发捕获的异常,但如果可能的话,使用python样式的输出。
相关答案依赖于以Windows为中心的平台来实现所需的结果,这不合适,不保留原始异常或未实现所需的python异常样式行为:
Get error message from ctypes windll
更新:
再进行一些挖掘之后,似乎在这种方法中的任何地方加注都会触发段错误。没有一个明智的解决方法。
答案 0 :(得分:0)
不是解决方案,而是一种解决方法:
手动收集错误信息(使用traceback
和inspect
),打印到sys.stderr
,然后返回指向CTypes错误单例的指针(在forbiddenfruit中完成)可防止发生段错误。
输出将是:
(为简便起见,此处未使用某些方法,因为它们没有为解决方案增加任何价值,我选择了pytest样式错误格式。)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except BaseException as be:
# Traceback will not help use here, assemble a custom error message:
from custom_inspect_utils import get_calling_expression_recursively
import sys
calling_file, calling_expression = get_calling_expression_recursively()
indentation = " "*(len(calling_expression)-len(calling_expression.lstrip()))
print(f"\n{calling_file}\n>{calling_expression}E{indentation}{type(be).__name__}: {be}", file=sys.stderr)
print(f"\n\tAs this package patches primitive types, the python RTE also raised:", file=sys.stderr)
return ErrorSingleton
例如修补list
以实现__rshift__
之后,现在[1,2,3] >> wrong_target
所期望的CustomException
表达式将首先输出
source_file.py:330 (method_name)
> [1,2,3] >> wrong_target
E CustomException: Message.
后跟一个TypeError
:
TypeError: unsupported operand type(s) for >>: 'list' and 'WrongType'