Python C API 使用详解(二)
- 2020 年 1 月 8 日
- 筆記
简介
介绍Python C API中的列表、元组、字典的使用,详细的进行了API中方法的介绍。
Python List API
List API 简单介绍
int PyList_Check(PyObject *p) 判断是否是一个Python List(列表)
PyObject* PyList_New(Py_ssize_t len) 创建一个列表
Py_ssize_t PyList_Size(PyObject *list) 获取列表元素的个数 len(list)
Py_ssize_t PyList_GET_SIZE(PyObject *list) 和PyList_Size 一样,但是就是没有错误检查
PyObject PyList_GetItem(PyObject list, Py_ssize_t index) 从列表里面获取一个元素,计数器不会加1
PyObject PyList_GET_ITEM(PyObject list, Py_ssize_t i) 和PyList_GetItem一样,但是就是没有错误检查
int PyList_SetItem(PyObject list, Py_ssize_t index, PyObject item) 设置别表指定位置的值,下标的所在的位置必须是有值的,并且是有效的
void PyList_SET_ITEM(PyObject list, Py_ssize_t i, PyObject o) 和PyList_SetItem一样,但是就是没有错误检查
int PyList_Insert(PyObject list, Py_ssize_t index, PyObject item) 在列表指定位置插入值 list.insert(index, item)
int PyList_Append(PyObject list, PyObject item) 在列表尾部追加值 list.append(item)
PyObject PyList_GetSlice(PyObject list, Py_ssize_t low, Py_ssize_t high) 获取列表里面一段切片数据,一段指定范围的数据 list[low:higt]
int PyList_SetSlice(PyObject list, Py_ssize_t low, Py_ssize_t high, PyObject itemlist) 设置列表分片数据,指定列表范围的数据 list[low:higt] = itemlist
int PyList_Sort(PyObject *list) 对列表数据进行排序 list.sort()
int PyList_Reverse(PyObject *list) 把列表里面的所有数据反转 list.reverse()
PyObject PyList_AsTuple(PyObject list) 将Python列表转为Python元组 tuple(list)
实例
注意事项: 不限制大小的Python列表对象,应该用Append初始化数据
设置大小的Python列表对象,应该用SetItem初始化数据, 如果用Append的话,会出现" 段错误 (核心已转储) "的情况
头文件
// // Created by lanyulei on 18-9-3. // #ifndef PRINT_DEMO1_PYLIST_H #define PRINT_DEMO1_PYLIST_H #include <Python.h> #include "print.h" // 创建一个固定大小的列表 void ListNumber(); // 创建一个可以无限扩展的列表 void ListExpansion(); #endif //PRINT_DEMO1_PYLIST_H
源文件
// // Created by lanyulei on 18-9-3. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include "pyList.h" // 有长短限制的列表 void ListNumber() { PyObject* pyList = PyList_New(3); // 创建一个大小为3的列表 PyObject* pyId = Py_BuildValue("i", 123); // 创建Python 整型对象 PyList_SetItem(pyList, 0, pyId); // 将Python整型对象插入到Python列表对象中 PyObject* pyName = Py_BuildValue("s", "lanyulei"); // 创建一个字符串python对象 PyList_SetItem(pyList, 1, pyName); // 插入到Python列表对象里面去 PyObject* pyFloat = Py_BuildValue("f", 23.98f); // 创建一个浮点类型的Python对象 PyList_SetItem(pyList, 2, pyFloat); // 将其插入到Python列表对象中 int listLength = PyList_Size(pyList); // 获取列表的长度 printf("列表长度: %dn", listLength); print_pyobject(pyList); // 打印列表数据 PyObject* pyName2 = Py_BuildValue("s", "LanYuLei"); // 创建一个字符串python对象 PyList_Insert(pyList, 1, pyName2); // 在下标为1的位置插入一条数据 print_pyobject(pyList); // 打印列表数据 printf("------------sort-------------n"); PyList_Sort(pyList); // 对列表进行排序 print_pyobject(pyList); // 打印列表数据 printf("---------------reverse--------------n"); PyList_Reverse(pyList); // 反转列表数据 print_pyobject(pyList); // 打印列表数据 printf("----------------slice----------------n"); PyObject* pySlice = PyList_GetSlice(pyList, 1, 3); // 获取分片数据 print_pyobject(pySlice); // 打印分片数据 } // 没有大小限制的列表 void ListExpansion(){ PyObject* pyList = PyList_New(0); // 创建一个没有大小限制的列表,所以参数为 0 PyObject* pyId = Py_BuildValue("i", 123); // 创建Python 整型对象 PyList_Append(pyList, pyId); // 将Python整型对象追加到Python列表对象中 PyObject* pyName = Py_BuildValue("s", "lanyulei"); // 创建一个字符串python对象 PyList_Append(pyList, pyName); // 追加到Python列表对象里面去 PyObject* pyFloat = Py_BuildValue("f", 23.98f); // 创建一个浮点类型的Python对象 PyList_Append(pyList, pyFloat); // 将其追加到Python列表对象中 print_pyobject(pyList); PyObject* py_data = PyList_GetItem(pyList, 0); // 获取下标为0的数据 print_pyobject(py_data); }
Python Tuple API
Tuple API 简单介绍
int PyTuple_Check(PyObject *p) 判断是否是一个元组对象
PyObject* PyTuple_New(Py_ssize_t len) 创建一个Python元组对象,注意元组创建是必须设置长度的,如果设置长度为0,则这个元组对象是一个空的元组
Py_ssize_t PyTuple_Size(PyObject *p) 获取元组的长度,即元组的大小
Py_ssize_t PyTuple_GET_SIZE(PyObject *p) 和PyTuple_Size一样,只不过这个方法没有错误检查的机制
PyObject PyTuple_GetItem(PyObject p, Py_ssize_t pos) 获取元组内指定下标的值
PyObject PyTuple_GET_ITEM(PyObject p, Py_ssize_t pos) 和PyTuple_GetItem一样,只不过这个方法没有错误检查的机制
PyObject PyTuple_GetSlice(PyObject p, Py_ssize_t low, Py_ssize_t high) 获取分片数据 p[lwo, higt]
int PyTuple_SetItem(PyObject p, Py_ssize_t pos, PyObject o) 设置元组指定下标的值
void PyTuple_SET_ITEM(PyObject p, Py_ssize_t pos, PyObject o) 和PyTuple_SetItem一样,只不过这个方法没有错误检查的机制
int _PyTuple_Resize(PyObject **p, Py_ssize_t newsize) 改变元组的大小
实例
头文件
// // Created by lanyulei on 18-9-4. // #ifndef PRINT_DEMO1_PYTUPLE_H #define PRINT_DEMO1_PYTUPLE_H #include <Python.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include "print.h" // 元组的使用 void test_tuple(); #endif //PRINT_DEMO1_PYTUPLE_H
源文件
// // Created by lanyulei on 18-9-4. // #include "pyTuple.h" void test_tuple(){ PyObject* pyTuple = PyTuple_New(3); // 创建一个元组 PyObject* pyId = Py_BuildValue("i", 1); // 创建一个Python整型对象 PyTuple_SetItem(pyTuple, 0, pyId); // 向指定的下标传递数据 PyObject* pyString = Py_BuildValue("s", "lanyulei"); // 创建一个Python字符串对象 PyTuple_SetItem(pyTuple, 1, pyString); PyObject* pyFloat = Py_BuildValue("f", 165.46f); // 创建一个Python浮点对象 PyTuple_SetItem(pyTuple, 2, pyFloat); int tupleLength = PyTuple_Size(pyTuple); printf("pyTuple size: %dn", tupleLength); print_pyobject(pyTuple); printf("----------------------PyTuple_GetItem--------------------------n"); PyObject* pyData = PyTuple_GetItem(pyTuple, 0); // 获取元组指定下标的数据 print_pyobject(pyData); printf("------------------------遍历元组--------------------------n"); // 遍历元组数据 for (int i = 0; i < PyTuple_Size(pyTuple); i++){ PyObject* pyData = PyTuple_GetItem(pyTuple, i); print_pyobject(pyData); } printf("------------------------获取分片数据--------------------------n"); PyObject* pySlice = PyTuple_GetSlice(pyTuple, 1, PyTuple_Size(pyTuple)); // 获取切片数据 print_pyobject(pySlice); printf("------------------------修改元组长度--------------------------n"); printf("原始长度: %dn", tupleLength); _PyTuple_Resize(&pyTuple, 5); // 修改元组长度,第一个参数是一个指针 printf("resize tuple length: %ldn", PyTuple_Size(pyTuple)); }
Python Dict API
Dict API 简单介绍
int PyDict_Check(PyObject *p) 判断对象是不是一个字典
PyObject* PyDict_New() 创建一个Python对象
void PyDict_Clear(PyObject *p) 清空Python对象的数据
int PyDict_Contains(PyObject p, PyObject key) 判断字典内是否存在一个键值数据
PyObject PyDict_Copy(PyObject p) 拷贝一个字典的数据,产生一个新的Python字典对象
int PyDict_SetItem(PyObject p, PyObject key, PyObject *val) 给Python字典对象设置新的键值数据
int PyDict_SetItemString(PyObject p, const char key, PyObject *val) 和PyDict_SetItem类似,只不过键是C语言char数据类型的数据
int PyDict_DelItem(PyObject p, PyObject key) 删除Python键值数据
int PyDict_DelItemString(PyObject p, const char key) 和PyDict_DelItem类似,只不过键是C语言char数据类型的数据
PyObject PyDict_GetItem(PyObject p, PyObject *key) 获取Python字典对象的键的值
PyObject PyDict_GetItemWithError(PyObject p, PyObject *key) 和PyDict_GetItem一样,只不过返回上下文的错误信息
PyObject PyDict_GetItemString(PyObject p, const char *key) 和PyDict_GetItem一样,只不过键值C语言中char数据类型的数据
PyObject PyDict_SetDefault(PyObject p, PyObject key, PyObject default) 设置Python字典对象的默认值,当获取的Key不存在的时候则返回当前的默认数据 dict.setdefault()
PyObject PyDict_Items(PyObject p) 返回一个Python字典对象所有数据的PyListObject, dict.items()
PyObject PyDict_Keys(PyObject p) 返回一个Python字典对象的所有的Key数据 dict.keys()
PyObject PyDict_Values(PyObject p) 返回一个Python字典对象的所有Value数据 dict.values()
Py_ssize_t PyDict_Size(PyObject *p) 获取Python字典的大小 len(dict)
int PyDict_Next(PyObject p, Py_ssize_t ppos, PyObject pkey, PyObject pvalue) 遍历获取Python字典对象的所有数据, 下面是官方提供的例子
PyObject *key, *value; Py_ssize_t pos = 0; // 初始值必须为0, 表示遍历所有Python字典对象数据 while (PyDict_Next(self->dict, &pos, &key, &value)) { /* do something interesting with the values... */ ... } PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(self->dict, &pos, &key, &value)) { long i = PyLong_AsLong(value); if (i == -1 && PyErr_Occurred()) { return -1; } PyObject *o = PyLong_FromLong(i + 1); if (o == NULL) return -1; if (PyDict_SetItem(self->dict, key, o) < 0) { Py_DECREF(o); return -1; } Py_DECREF(o); }
int PyDict_Merge(PyObject a, PyObject b, int override) 将b字典内的数据,加入到a字典中去,override表示是否覆盖数据,如果override为true则覆盖数据,反之亦然
int PyDict_Update(PyObject a, PyObject b) 把b字典中的数据加入到a字典中,如果a和b出现相同的key,则b直接更新a中key对应的值
实例
头文件
// // Created by lanyulei on 18-9-5. // #ifndef PRINT_DEMO1_PYDCIT_H #define PRINT_DEMO1_PYDCIT_H #include <stdio.h> #include <stdlib.h> #include <string.h> #include <Python.h> #include "print.h" // 字典练习 void test_dict(); #endif //PRINT_DEMO1_PYDCIT_H
源文件
// // Created by lanyulei on 18-9-5. // #include "pyDcit.h" void test_dict() { //创建dict PyObject* py_dict_1 = PyDict_New(); //检查PyObject是不是一个字典 int ret = PyDict_Check(py_dict_1); if (ret) { printf("is dictn"); } else { printf("is not dictn"); } PyObject *py_key_account_id = Py_BuildValue("s", "account_id"); PyObject *py_value_account_id = Py_BuildValue("i", 1238); //向dict添加一个key-value PyDict_SetItem(py_dict_1, py_key_account_id, py_value_account_id); PyObject *py_value_account_name = Py_BuildValue("s", "mono"); PyDict_SetItemString(py_dict_1, "account_name", py_value_account_name); PyObject *py_key1 = Py_BuildValue("i", 1); PyObject *py_key1_value = Py_BuildValue("i", 2399); PyDict_SetItem(py_dict_1, py_key1, py_key1_value); //获取字典的大小 int dict_len = PyDict_Size(py_dict_1); printf("dict_len=%dn", dict_len); print_pyobject(py_dict_1); //从字典删除一个key PyDict_DelItem(py_dict_1, py_key_account_id); printf("del item: py_key_account_id--------------------------n"); print_pyobject(py_dict_1); //删除一个不存在的key PyObject *py_not_existing_key = Py_BuildValue("s", "name"); PyDict_DelItem(py_dict_1, py_not_existing_key); printf("del item: py_not_existing_key------------------n"); print_pyobject(py_dict_1); //------------------------------------------------------- //PyDict_DelItemString(py_dict_1, "account_name"); //printf("del item: account_name -----------------n"); //print_pyobject(py_dict_1); PyObject *py_key_account_name = Py_BuildValue("s", "account_name"); //从字典中获取一个key-value PyObject *py_value1 = PyDict_GetItem(py_dict_1, py_key_account_name); printf("get item: account_name-----------------------n"); print_pyobject(py_value1); printf("n"); //从字典中获取一个key-value PyObject *py_value2 = PyDict_GetItemString(py_dict_1, "account_name"); printf("get item string: account_name -------------------n"); print_pyobject(py_value2); printf("n"); //----------------------------------------------------------- //从字典中获取所有key-value对 PyObject *py_items = PyDict_Items(py_dict_1); printf("get items --------------------------n"); print_pyobject(py_items); printf("n"); //-------------------------------------- //从字典中获取所有key PyObject *py_keys = PyDict_Keys(py_dict_1); printf("get keys -------------------------n"); print_pyobject(py_keys); printf("n"); //------------------------------------------------ //从字典获取所有值 PyObject *py_values = PyDict_Values(py_dict_1); printf("get values -----------------------n"); print_pyobject(py_values); printf("n"); //------------------------------------------------------ //遍历字典 PyObject *key, *value; Py_ssize_t pos = 0; printf("dict next -------------------n"); while (PyDict_Next(py_dict_1, &pos, &key, &value)) { print_pyobject(key); printf("="); print_pyobject(value); printf("n"); } //--------------------------------------------- PyObject *py_dict_2 = PyDict_New(); PyObject *py_key21 = Py_BuildValue("i", 101); PyObject *py_key21_value = Py_BuildValue("i", 60000); PyDict_SetItem(py_dict_2, py_key21, py_key21_value); PyObject *py_value_level = Py_BuildValue("i", 30); PyDict_SetItemString(py_dict_2, "account_level", py_value_level); PyObject *py_value_account_name2 = Py_BuildValue("s", "myname"); PyDict_SetItemString(py_dict_2, "account_name", py_value_account_name2); printf("dict_2 items --------------------n"); print_pyobject(py_dict_2); //把py_dict_2的所有数据添加到py_dict_1 PyDict_Merge(py_dict_1, py_dict_2, 0); printf("dict merge: override=0, -----------------n"); print_pyobject(py_dict_1); //---------------------------------------- PyObject *py_dict_3 = PyDict_New(); PyObject *py_value_score = Py_BuildValue("i", 10000); PyDict_SetItemString(py_dict_3, "account_score", py_value_score); PyObject *py_value_account_name3 = Py_BuildValue("s", "sujin"); PyDict_SetItemString(py_dict_3, "account_name", py_value_account_name3); //将py_dict_3的所有数据添加到py_dict_1, 这个api相当于PyDict_Merge第三个参数为1的情况. PyDict_Update(py_dict_1, py_dict_3); printf("dict update ----------------------n"); print_pyobject(py_dict_1); //--------------------------------------------- const char *check_key = "account_name"; PyObject *py_check_key = Py_BuildValue("s", check_key); //在字典中检查是否存在这个key ret = PyDict_Contains(py_dict_3, py_check_key); if (ret) { printf("has key: %sn", check_key); } else { printf("no key: %sn", check_key); } //------------------------------------------------- //清空字典的所有数据 PyDict_Clear(py_dict_3); printf("dict clear ---------------------n"); print_pyobject(py_dict_3); }
根据数据类型打印数据的方法
头文件
// // Created by lanyulei on 18-9-1. // #ifndef PRINT_DEMO1_PRINT_H #define PRINT_DEMO1_PRINT_H #include <Python.h> void print_pyobject(PyObject *py_obj); #endif //PRINT_DEMO1_PRINT_H
源文件
// // Created by lanyulei on 18-9-1. // #include "print.h" #include <stdio.h> #include <string.h> #include <stdlib.h> // Python 中的浮点类型, 都是double void print_pyobject(PyObject *py_obj){ if (py_obj == NULL){ printf("NULL"); return; } if (PyInt_Check(py_obj)){ // int int ival = PyInt_AsLong(py_obj); printf("我是整型,ival = %dn", ival); } else if (PyLong_Check(py_obj)){ // long long long lval = PyLong_AsLongLong(py_obj); printf("我是长整型,lval = %lldn", lval); } else if (PyFloat_Check(py_obj)){ // float/double double fval = PyFloat_AS_DOUBLE(py_obj); printf("我是浮点类型,fval = %lfn", fval); } else if (PyBool_Check(py_obj)){ // bool int bval = PyInt_AsLong(py_obj); if (bval == 1){ printf("我是布尔类型,bval = truen"); }else { printf("我是布尔类型,bval = falsen"); } } else if (PyString_Check(py_obj)){ // 不包含中文的字符串 char *str = PyString_AsString(py_obj); printf("我是不包含中文的字符串,str = %sn", str); } else if (PyUnicode_Check(py_obj)){ // unicode 含有中文的字符串 // 首先将unicode转成utf-8 PyObject *py_utf8 = PyUnicode_AsUTF8String(py_obj); char *ustr = PyString_AsString(py_utf8); printf("我是unicode,ustr = %sn", ustr); } else if (PyList_Check(py_obj)){ // Python list printf("我是列表,"); printf("[n"); for (int i = 0;i < PyList_Size(py_obj); i++){ PyObject *py_data = PyList_GetItem(py_obj, i); print_pyobject(py_data); } printf("]n"); } else if (PyTuple_Check(py_obj)){ // Python tuple printf("我是元组,"); printf("(n"); for (int i = 0;i < PyTuple_Size(py_obj); i++){ PyObject *py_data = PyTuple_GetItem(py_obj, i); print_pyobject(py_data); } printf(")n"); } else if (PyDict_Check(py_obj)){ // Python dict PyObject *key, *value; Py_ssize_t pos = 0; printf("我是字典,"); printf("{n"); while (PyDict_Next(py_obj, &pos, &key, &value)) { print_pyobject(key); printf("="); print_pyobject(value); } printf("}n"); } }
main函数
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 初始化Python虚拟机 Py_Initialize(); // 判断Python虚拟机是否成功 if (Py_IsInitialized() == 0){ printf("fal to initialize Pythonn"); return -1; } printf("server startn"); // 退出Python虚拟机 Py_Finalize(); return 0; }