Python中C API如何引用计数器
admin
2023-07-20 07:42:24
0

简介

Python的内存管理是通过对象的引用计数器来实现的,对象的创建会将引用计数器加1,被引用一次则引用计数器就会加1,反之解除引用时,则引用计数器就会减1,当Python对象的引用计数器为0的时候,则这个对象就会被回收和释放。

这种内存管理的方式是有一定的弊端的,一是它需要额外的空间维护引用计数,二是它不能解决对象的“循环引用”的问题,因此,也有很多语言比如Java并没有采用该算法做来垃圾的回收机制。

Python代码实例

import sys

def test_refcount(a):
    print("func a refcount: {}".format(sys.getrefcount(a)))

if __name__ == '__main__':

    // 直接创建Python对象
    a = 189987319
    print("a refcount: {}".format(sys.getrefcount(a)))

    // 调用一次Python对象a,则引用计数器加1
    b = a
    print("b, a refcount: {}".format(sys.getrefcount(a)))

    // 存入列表,字段,或者元组中,引用计数器都会加1
    c = [a]
    print("c, a refcount: {}".format(sys.getrefcount(a)))

    // 使用函数调用的时候,传参的时候引用计数器加1,调用的时候引用计数器也会加1,因此是加2
    test_refcount(a)

结果:
a refcount: 1
b, a refcount: 2
c, a refcount: 3
func a refcount: 5

Python C API中管理及释放Python对象

void Py_INCREF(PyObject *o)  Python对象引用计数器加1,该对象不能为NULL,否则会报错

void Py_XINCREF(PyObject *o)   Python对象引用计数器加1,该对象可以为NULL,但是引用计数器未生效

void Py_DECREF(PyObject *o)   Python对象的引用计数器减1,该对象不能为NULL,否则会报错

void Py_XDECREF(PyObject *o)   Python对象引用计数器减1,该对象可以为NULL,但是引用计数器未生效

void Py_CLEAR(PyObject *o)  直接将Python应用计数器清0

C代码实例

头文件

//
// Created by lanyulei on 18-9-9.
//

#ifndef PRINT_DEMO1_PYREFCOUNT_H
#define PRINT_DEMO1_PYREFCOUNT_H

#include 
#include 
#include 
#include 

void pyRefCount();

#endif //PRINT_DEMO1_PYREFCOUNT_H

源文件

//
// Created by lanyulei on 18-9-9.
//

#include "pyRefCount.h"

// Python对象的保留及释放
void pyRefCount(){

    PyObject* py_ival = Py_BuildValue("i", 56486);  // 创建对象
    printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival));   // 打印Python对象的引用计数器

    Py_XINCREF(py_ival);   // Python对象的引用计数器加1
    printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival));   // 打印Python对象的引用计数器

    Py_XDECREF(py_ival);    // Python对象的引用计数器减1
    printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival));   // 打印Python对象的引用计数器

    Py_CLEAR(py_ival);   // Python对象的引用计数器清0
    printf("Py_BuildValue: py_ival refcount: %ld\n", Py_REFCNT(py_ival));   // 打印Python对象的引用计数器
}

main.cpp

#include "pyRefCount.h"

int main() {

    // 初始化Python虚拟机
    Py_Initialize();
    // 判断Python虚拟机是否成功
    if (Py_IsInitialized() == 0){
        printf("fal to initialize Python\n");
        return -1;
    }

    printf("server start\n");
    pyRefCount();

    // 退出Python虚拟机
    Py_Finalize();
    return 0;
}

初始化Python脚本路径

Python虚拟机在运行的时候,import一个模块的时候,如果这个模块没有被加载过,则Python虚拟机就会在执行程序的所在路径搜索这个脚本,如果找到脚本文件就将它加载,如果没有找到,就会从sys.path中的所有路径去搜索,如果找到脚本文件就加载,反之则报错。

Python下的sys.path

打印所有的sys.path下的路径

>>> import sys
>>> sys.path
['', 'C:\\WINDOWS\\SYSTEM32\\python27.zip', 'D:\\software\\Python2\\DLLs', 'D:\\software\\Python2\\lib', 'D:\\software\\Python2\\lib\\plat-win', 'D:\\software\\Python2\\lib\\lib-tk', 'D:\\software\\Python2', 'D:\\software\\Python2\\lib\\site-packages', 'D:\\software\\Python2\\Lib\\site-packages\\pytesser_v0.0.1']

将当前路径加入到sys.path

>>> import os
>>> import sys
>>> sys.path.append(os.getcwd())
>>> sys.path
['', 'C:\\WINDOWS\\SYSTEM32\\python27.zip', 'D:\\software\\Python2\\DLLs', 'D:\\software\\Python2\\lib', 'D:\\software\\Python2\\lib\\plat-win', 'D:\\software\\Python2\\lib\\lib-tk', 'D:\\software\\Python2', 'D:\\software\\Python2\\lib\\site-packages', 'D:\\software\\Python2\\Lib\\site-packages\\pytesser_v0.0.1', 'C:\\WINDOWS\\system32']

C/C++初始化Python脚本路径

头文件

//
// Created by win7 on 2018/9/10.
//

#ifndef INC_20180910_PYINIT_H
#define INC_20180910_PYINIT_H

#include 
#include 
#include 
#include 

bool initPython();

#endif //INC_20180910_PYINIT_H

源文件

//
// Created by win7 on 2018/9/10.
//

#include "pyInit.h"

bool initPython() {
    char scriptPath[128];
    sprintf(scriptPath, "sys.path.append('%s')", "./script");

    // 向Python注册我们的脚本路径
    PyRun_SimpleString("import sys");
    PyRun_SimpleString(scriptPath);

    PyRun_SimpleString("print sys.path");
    return true;
}

相关内容

热门资讯

取消、推迟!美伊谈判再生变数 当地时间6月18日晚,据美国有线电视新闻网(CNN)报道,白宫方面表示,由于下一阶段谈判的后勤安排尚...
男厨师光膀子救卡喉女顾客被质疑... 6月14日,江苏苏州一家烤鱼店内,一名女顾客用餐时突然发生异物卡喉。同行友人和店员立刻采用海姆立克急...
首届超级智能体大赛启幕 广州向... 羊城晚报全媒体记者 詹淑真 杭莹 方寸之间,定格智能时代;赛场之上,激荡湾区创新。 6月18日上午,...
“618”看大促丨“以旧换新+... 央广网北京6月18日消息(记者焦浩)据中央广播电视总台经济之声《天下财经》报道,今年的“618”大促...
怎么挑选适配沈阳城乡场景的太阳... 沈阳户外照明行业发展背景 随着沈阳城镇化建设与乡村振兴战略的持续推进,城乡道路、市政公园、文旅景区、...
83岁拜登舞台再犯迷糊,神情茫... 6 月 18 日消息,美国芝加哥奥巴马总统中心开幕仪式现场曝出极具争议的一幕,各路前总统齐聚的隆重场...
中国民企5年百亿救活英国百年钢... 现实版“农夫与蛇”的故事正在上演。六年前,中国民营企业敬业钢铁掏钱救活了一家英国百年钢企。五年后,英...
美国4位前第一夫人罕见同框,为... 当地时间6月18日,美国四位前总统和他们各自的夫人,相聚在了芝加哥,参加“贝拉克·奥巴马图书馆”的盛...
科学与健康丨我国科研团队成功破... 午间的强光,是农作物生长的“双刃剑”,看似充沛的光照能滋养作物,却会引发“光合午休”现象,造成产量大...
特朗普吐露的真相,比战争结局更... 中东大战,似乎戛然而止了。我相信,很多人可能还不相信自己眼睛,怎么打得这么虎头蛇尾?为什么美国突然又...