您好,登录后才能下订单哦!
这篇文章给大家分享的是有关Python中C API如何引用计数器的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
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
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 <stdio.h> #include <stdlib.h> #include <string.h> #include <Python.h> 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虚拟机在运行的时候,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 <stdio.h> #include <stdlib.h> #include <string.h> #include <Python.h> 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; }
感谢各位的阅读!关于“Python中C API如何引用计数器”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。