Python C API 使用詳解(二)
介紹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
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("列表長度: %d\n", 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: %d\n", 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("原始長度: %d\n", tupleLength);
_PyTuple_Resize(&pyTuple, 5); // 修改元組長度,第一個參數是一個指針
printf("resize tuple length: %ld\n", 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 dict\n");
}
else
{
printf("is not dict\n");
}
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=%d\n", 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: %s\n", check_key);
}
else
{
printf("no key: %s\n", 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 = %d\n", ival);
} else if (PyLong_Check(py_obj)){
// long
long long lval = PyLong_AsLongLong(py_obj);
printf("我是長整型,lval = %lld\n", lval);
} else if (PyFloat_Check(py_obj)){
// float/double
double fval = PyFloat_AS_DOUBLE(py_obj);
printf("我是浮點類型,fval = %lf\n", fval);
} else if (PyBool_Check(py_obj)){
// bool
int bval = PyInt_AsLong(py_obj);
if (bval == 1){
printf("我是布爾類型,bval = true\n");
}else {
printf("我是布爾類型,bval = false\n");
}
} else if (PyString_Check(py_obj)){
// 不包含中文的字符串
char *str = PyString_AsString(py_obj);
printf("我是不包含中文的字符串,str = %s\n", 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 = %s\n", 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 Python\n");
return -1;
}
printf("server start\n");
// 退出Python虛擬機
Py_Finalize();
return 0;
}
Python C API 使用詳解(二)