首页 > 编程语言 >Python/C API 异常处理

Python/C API 异常处理

时间:2023-11-16 17:35:45浏览次数:42  
标签:函数 指示器 Python PyErr PyObject API NULL 异常

Python/C API 异常处理(部分)

Python/C API 中的异常处理与Unix系统中的errno 变量类似,每个线程都有一个全局的异常指示器,该指示器只记录最后一次发生的异常。大多数函数都不会在成功执行时清除该指示器,但会在异常发生时及时设置该指示器。大部分函数函数也都会返回一个标志来指示其执行过程中是否发生异常,如果函数的返回类型为指针,则返回NULL时表示有异常发生;若返回类型为整数,返回-1表示有异常发生(例外:PyArg_*() 函数返回1表示成功,0表示失败)。

若函数A调用函数B,并且当函数B发生异常必定导致函数A失败时,函数A不能再次设置异常指示器,因为函数B已经设置了。

异常指示器拥有同sys.exc_info()返回值相同的三个对象。

1 异常处理函数

  • void PyErr_PrintEx(int set_sys_last_vars)
  • void PyErr_Print() // set_sys_last_vars=1
    将标准traceback打印至sys.stderr,并且清除错误指示器。只有错误指示器被设置后才能调用这个函数,否则会造成严重的错误。如果参数set_sys_last_vars 不为0,则变量sys.last_typesys.last_valuesys.last_traceback 将会分别被设置为北大印异常对象的类型、值、traceback。

  • PyObject * PyErr_Occurred()
    返回borrowed引用。检查错误指示器是否被设置,是则返回异常type,否则返回NULL。因为是borrowed引用,所以不用调用Py_DECREF()
    注意:不要将返回值与一个特定的异常直接进行比较,要用PyErr_ExceptionMatches() 进行比较。

  • int PyErr_GiveExceptionMatches(PyObject *given, PyObject *exc)

  • int PyErr_ExceptionMatches(PyObject *exc) // given=PyErr_Occurred()
    比较given异常是否与exc匹配,后者只能在确实有异常发生时才能调用,否则会发生内存的非法访问。如果exc是一个class对象,则当given是exc的子类时返回true;如果exc为一个元组,则将given与exc中的每个成员进行匹配检查。

  • void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
    在一些情况下,函数PyErr_Fetch() 的返回值可能是unnormalized(*exc是一个class对象,但*val不是该class的实例),该函数能够将*val实例化为exc类型,若*val已经被实例化为*exc类型,则该函数不会进行任何操作。将*normalization推迟是为了提高性能。
    注意:该函数不会将__traceback__设置到*val中,如果需要这么做,需要这么做

if (tb != NULL)
{
    PyException_SetTraceback(val, tb);
}
  • void PyErr_Clear()
    清除错误指示器, 如果错误指示器没有设置,则不会有任何影响。

  • void PyErr_Fetch(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)
    从错误指示器中取回三个变量,并将其存入提供的参数中。如果错误指示器没有设置,三个参数将被设置为NULL;否则,错误指示器将会被清空并且调用者将获得三个对象的引用。即使type对象不为NULL,value对象和traceback对象也有可能为NULL。
    注意:当代码中要处理异常或需要保存异常指示器时,通常会调用该函数。

  • void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
    将三个参数提供的信息设置到错误指示器中。若在这之前错误指示器已经被设置,则会先将其清除。如果被传入的对象为NULL,错误指示器将会被清除。不要将type==NULL && (value!=NULL || traceback!=NULL) 作为参数传入。参数type一定要有效且是一个class。
    警告:该函数会take away每个对象的引用,所以在调用之前,你一定要拥有每个对象的引用,调用之后,你就会失去它们。
    注意:在需要暂时设置异常指示器时可以调用该函数。

  • void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)
    获取刚捕获异常的信息(刚捕获的异常,非重新抛出的异常),返回每个对象的新的引用、每个对象都有可能为NULL。该函数不会改变异常信息状态。

  • void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)
    设置异常信息(刚捕获的异常,非重新抛出的异常)。该函数会steal参数的引用。若希望清除异常状态,可将NULL传给每个参数。

  • void PyErr_SetString(PyObject *type, const char *message)
    该函数是最常用 的错误指示器设置方式。第一个参数指定异常类型,其一般为一个标准异常类型(比如PyExc_RuntimeError),用户不需要增加其引用计数;第二个参数是错误信息,使用utf8编码。

  • void PyErr_SetObject(PyObject *type, PyObject *value)
    同PyErr_SetString()类似,可为异常对象设置任意的对象。

  • PyObject * PyErr_Format(PyObject *exception, const char *format, …)
    返回值一直为NULL。该函数设置函数指示器并返回NULL,参数exception要是一个Python异常类,参数format和其后的参数与函数PyUnicode_FromFormat() 中的参数有相同的含义,参数format为ASCII编码字符串。

  • void PyErr_SetNone(PyObject *type)
    –> PyErr_SetObject(type, Py_None)

  • void PyErr_BadArgument()
    –>PyErr_SetString(PyExc_TypeError, message),其中message为非法参数激活内置操作时的信息。

  • PyObject * PyErr_NoMemory()
    –>PyErr_SetNone(PyExc_MemoryError)
    返回值一直为NULL。可在发生分配内存失败时,作为返回值用 return PyErr_NoMemory()

  • PyObject * PyErr_SetFromErrno(PyObject *type)
    返回值一直为NULL。这其实是个转换函数,当C库函数返回错误并设置errno时,抛出一个异常。该函数会构造一个元组对象,其第一个值为整数errno,第二个值是对应的错误信息(从函数strerror() 函数获得),然后调用PyErr_SetObject(type, object)。在Unix系统中,当errno为EINTR时,表示信号中断了系统调用,该函数会调用PyErr_CheckSignals(),若该函数设置了错误指示器,则保留该错误指示器。因为该函数返回NULL,所以在系统API失败时可直接return PyErr_SetFromErrno(type)

  • PyObject * PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
    该函数是一个很方便抛出ImportError异常的函数。参数msg设置为异常信息字符串,参数name和path都可以为NULL,不为NULL时要设置为ImportError异常对应的name和path属性。

  • void PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)

  • void PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
  • void PyErr_SyntaxLocation(const char *filename, int lineno)
    为当前异常设置对应的文件、行、偏移信息。

2 异常对象

  • PyObject * PyException_GetTraceback(PyObject *ex)
    返回当前异常对象traceback的一个新的引用,就像在Python代码中使用__traceback__一样。若当前没有traceback信息,则返回NULL。

  • int PyException_SetTraceback(PyObject *ex, PyObject *tb)
    将异常对象ex的traceback信息设置为tb,若tb为Py_None则可清除相应的traceback信息。

  • PyObject * PyException_GetContext(PyObject *ex)
    返回异常对象ex的山下文信息(在处理ex期间抛出的另一个异常实例),返回值为一个新的引用,就像在Python中使用__context__一样。若没有,则返回NULL。

  • void PyException_SetContext(PyObject *ex, PyObject *ctx)
    设置ex的context为ctx,若ctx则清除ex的context。该函数会steal参数ctx的引用。

  • PyObject * PyException_GetCause(PyObject *ex)
    返回一个异常对应的实例或None,就像在Python代码中使用__cause__一样。

  • void PyException_SetCause(PyObject *ex, PyObject *cause)
    将与异常关联的异常原因设置为参数cause,cause的引用会被steal,若cause为NULL则会清除对应的cause。


 

标签:函数,指示器,Python,PyErr,PyObject,API,NULL,异常
From: https://www.cnblogs.com/lidabo/p/17836814.html

相关文章

  • C++调用Python3实战,和PyImport_ImportModule返回NULL问题解决
    LinuxC++调用Python3入门准备以下面的目录结构演示如何在LinuxC/C++调用python3。|--hello.py|--main.cpp|--CMakeLists.txt hello.py:python的脚本,里面有2个函数main.cpp:c++函数CMakeLists.txt:Cmake文件,生成makefilepython脚本示例python脚本hello.py内容如下,......
  • 揭示API重要性,以Assistants API为例
    2022年11月,ChatGPT问世,标志着人工智能领域取得了重大进展。OpenAI最近举办了首届开发者大会,将ChatGPT4.0升级到ChatGPT4.0-Turbo。新版本的ChatGPT不仅提高了响应速度,还将数据库更新到了2023年4月。而在自然语言处理能力方面,新版本通过显著提升上下文理解能力,扩展了上下文窗口至1......
  • 如何通过python实现导出题库到pdf?
    要通过Python实现将题库导出为PDF,你可以使用一些第三方库来处理PDF文件和生成内容。下面是一个基本的步骤和示例代码:安装所需的库:首先,你需要安装reportlab库,它是一个用于创建PDF文档的强大工具。你可以使用以下命令来安装该库:pipinstallreportlab创建PDF文档:使用reportlab库创建......
  • 基于pybind11实现C++程序中调用Python脚本增加C++程序扩展性
     文章目录前言一、pybind11与Python环境配置二、C++环境配置三、C++调用Python交互代码四、C++调用PythonDemo完整源码 前言Windows平台,在实际C++项目开发中,结合pybind11库,让python成为C++的脚本语言,可以大大提高C++程序的可扩展性,大大提高开发效率,特别......
  • C++通过pybind11调用Python 实现transpose
    在某些场合需要在C++实现类似numpy的numpy.transpose(a,axes)功能,但是很多库如NumCpp都没有提供这样的方法,只有二维矩阵的转置,没法进行多维矩阵任意维度的转换。比较简单的想法就是利用numpy现有的功能,在c++代码里面通过调用python来调用Numpy的transpose。直接调用Python提......
  • python基础之字典 Dictionary
      字典Dictionary¶在Python中,字典(Dictionary)是一种无序的、可变的数据类型,用于存储键-值(key-value)对的集合。字典是通过键来索引和访问值的,而不是通过位置。字典dictionary,在一些编程语言中也称为hash,map,是一种由键值对组成的数据结构。  基......
  • C++调用python踩坑记录
     目录0、参考文档及博客1、环境配置步骤2、C++调用python的方法代码框架:(同样来源于上面这篇博客,可用于测试环境配置成功与否)报错处理函数(1)处理方法一:PyErr_Print(2)处理方法二:PyErr_Fetch2.5、终极解决方案3、踩坑记录(1)python第三方库调用出错(2)python模块环......
  • 使用CURL获取速卖通详情的API接口
    作为一名程序员,我们经常需要与各种API接口打交道,以获取所需的数据并集成到我们的应用程序中。速卖通(AliExpress)是一个流行的跨境电商平台,提供了丰富的API接口供开发者使用。本文将介绍如何使用curl命令通过速卖通的API接口获取商品详情。在开始之前,确保你已经注册了速卖通开发者账......
  • 《流畅的Python》 读书笔记 第8章_对象引用、可变性和垃圾回收
    第8章_对象引用、可变性和垃圾回收本章的主题是对象与对象名称之间的区别。名称不是对象,而是单独的东西name='wuxianfeng'#name是对象名称'wuxianfeng'是个str对象variablesarelabels,notboxes变量是标注,而不是盒子引用式变量的名称解释本章还会讨论标识......
  • python生成 时间戳和日期格式
    1.获取当前日期要获取当前日期,我们可以使用datetime模块中的datetime类的now()方法。下面是获取当前日期的代码示例:importdatetimecurrent_date=datetime.datetime.now().date()print("当前日期:",current_date)#运行以上代码,输出的结果类似于:当前日期:2022-01-01#获取时......