Qt+Pyhton实现麒麟V10系统下word文档读写功能

目录

      • 前言
      • 1.C++调用python
        • 1.1 安装Python开发环境
        • 1.2 修改Qt工程配置
        • 1.3 初始化Python环境
        • 1.4 C++ 调用Python 函数
        • 1.5 常用的Python接口
      • 2.python虚拟环境
        • 2.1Python虚拟环境简介
        • 2.2 virtualenv 安装及使用
        • 2.3 在C++程序中配置virtualenv 虚拟环境
      • 3.python-docx库的应用
      • 4.总结

前言

我最近遇到一个这样的需求,即把某个软件中采集的数据按照特定的格式导出到world文档中。因为程序是用Qt开发的,所以想找一个满足要求的C++库,通过一番查询发现能完成这个需求的常用C++库有LibreOffice、OpenOffice。这两个库虽然能实现这一需求但是学习成本比较高,在规定的时间内完成这个需求比较困难。

这时只能将目光转向其他语言的读写word文档的库上,我发现python-docx 这个库不仅能实现需求而且学习成本很低,只要懂点Python几乎不需要额外花时间就能学会使用这个库。

本文主要从三个方面介绍了如何在Qt应用程序中调用Python实现数据导出到world文档中。这三个方面分别是C++调用python、在程序中使用Python虚拟环境及Python-docx库的基本应用。

1.C++调用python

1.1 安装Python开发环境

麒麟V10 默认安装了python3.8,但是没有安装C++调用Python需的头文件,在系统中找不到Python.h文件。安装Python 开发环境,执行下面的命令:

sudo apt-get update 
sudo apt-get install python3-dev

安装完成后会在/usr/include/python3.8 目录下看到需要的头文件。

1.2 修改Qt工程配置

新建Qt工程demo,并在pro文件中增加Python头文件和库的引用。

INCLUDEPATH += /usr/include/python3.8
LIBS += -L/usr/lib/python3.8/config-3.8-aarch64-linux-gnu -lpython3.8

1.3 初始化Python环境

 	//初始化Python C APIPy_Initialize();//将Python文件所在的目录添加到环境变量,以便能正确加载Python文件。PyRun_SimpleString("import sys");QString pyfilePath = QString::fromLocal8Bit("sys.path.append('%1')").arg(qApp->applicationDirPath() + "/python");qDebug() << "pyfilePath:" << pyfilePath;PyRun_SimpleString(pyfilePath.toLocal8Bit().data());QString printSysPath = "print(sys.path)";PyRun_SimpleString(printSysPath.toLocal8Bit().data());//加载Python文件,其中testdocx.py 所在的目录即为 qApp->applicationDirPath() + /python/testdocx.pyPyObject *pWriteWordModule = PyImport_ImportModule("testdocx");if(!pWriteWordModule){qDebug() << "import module faild!";//如果失败打印错误,方便调试PyErr_Print();}

上面的代码,首先初始化Python环境,然后设置Python文件搜索路径到path中,最后加载testdocx.py 文件。

1.4 C++ 调用Python 函数

假设testdocx.py 文件中的内容如下,定义了一个函数,并打印传进来的参数。

def writeWord(wordPath):print(wordPath)

在C++中调用这个函数

	//获取Python中定义的函数的指针PyObject *pFunc = PyObject_GetAttrString(pWriteWordModule, "writeWord");if(!pFunc){qDebug() << "get func faild!";}//初始化参数元组,其中包含一个参数PyObject *pTuple = PyTuple_New(1);QString wordFilePath = QString("%1/python/%2").arg(qApp->applicationDirPath()).arg(QString::fromLocal8Bit("xxx.docx"));//设置参数PyTuple_SetItem(pTuple, 0, Py_BuildValue("s", wordFilePath.toLocal8Bit().data()));//调用Python中的函数PyObject_CallObject(pFunc, pTuple);

运行程序,如果一切顺利的话会在终端打印:
/home/demo/bin/python/xxx.docx

1.5 常用的Python接口

Python C API参考文档地址
在这里插入图片描述

PyObject 在C++和Python混合编程中最常用的一个类型,所有对象类型都是这个类型的扩展。PyObject中包含了Python需要将对象的指针视为对象的信息。在一般的“release”版本中,它只包含对象的引用计数和指向相应类型对象的指针。实际上并没有任何东西被声明为PyObject,但是每个指向Python对象的指针都可以转换为PyObject*。必须使用宏Py_REFCNT和Py_TYPE来访问成员。下面是一些编程中常用的Python C API。

  • PyList_New 创建一个Python list 对象,返回类型为PyObject*;
  • PyDict_New 创建一个Python Dict 对象,返回类型为PyObject*;
  • PyTuple_New 创建一个Python 元组对象,返回类型为PyObject*;
  • Py_BuildValue 将C数据类型转换为Python对象,返回类型为PyObject*,下面是Py_BuildValue函数的原型:
    PyObject* Py_BuildValue(const char* format, …);其中,format是一个描述返回的Python对象的格式字符串,而…表示可变数量的参数列表,这些参数与格式字符串中指定的类型相对应。
    下面是一些常见的格式字符串和相应的参数列表:
    ‘()’:表示一个空元组。
    ‘(i)’:表示一个包含一个整数(参数为整数)的元组。
    ‘(ii)’:表示一个包含两个整数(参数为两个整数)的元组。
    ‘s’:表示一个字符串。
    ‘d’:表示一个浮点数。
    ‘z’:表示一个NULL指针或None。
    ‘O’:表示一个通用对象。
    下面是一个示例,演示如何使用Py_BuildValue函数将C数据类型转换为Python对象:
#include <Python.h>
int main(int argc, char* argv[]) {Py_Initialize();int x = 42;double y = 3.14;char* z = "Hello, World!";PyObject* result = Py_BuildValue("(iO)", x, Py_None);if (result == NULL) {PyErr_Print();return 1;}printf("Result: %s\n", PyUnicode_AsUTF8(result));Py_DECREF(result);Py_Finalize();return 0;
}
  • PyDict_SetItemString 设置字典键值对;
//函数原型
PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item);
//示例:
PyObject* pDictObj = PyDict_New();
PyObject* deviceNameObj = Py_BuildValue("s", deviceData.deviceName.toLocal8Bit().data());
PyDict_SetItemString(pDictObj, "deviceName", deviceNameObj);
  • PyList_Append 向列表中添加元素;
//函数原型
PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *);
//示例:
PyObject *PointDataListObj = PyList_New(0);
PyList_Append(PointDataListObj, pDictObj);
  • PyRun_SimpleString 在Python解释器中执行一个简单的 Python 代码字符串;
//函数原型
int PyRun_SimpleString(const char *command);
//示例
const char* code = "print('Hello, World!')";
int result = PyRun_SimpleString(code);
if (result == 0) {//执行成功printf("Successfully executed code.\n");
} else {//执行失败printf("Failed to execute code.\n");
}
  • PyImport_ImportModule 在C程序中导入Python模块;
//函数原型
PyObject* PyImport_ImportModule(const char *name);
//说明,该函数返回一个Python对象,表示导入的模块。如果导入成功,则返回该模块对象的引用,否则返回NULL。
//示例:
PyObject* mymodule = PyImport_ImportModule("mymodule");
if (mymodule != NULL) {printf("Successfully imported mymodule.\n");
} else {printf("Failed to import mymodule.\n");
}
  • PyObject_CallObject 在C中调用Python对象的方法和函数;
//函数原型
PyObject* PyObject_CallObject(PyObject *callable, PyObject *args);
//说明,callable是一个指向要调用的Python对象(如函数或方法)的指针,args是一个指向参数列表的指针。
//该函数返回调用结果,表示为Python对象。如果调用成功,则返回调用结果的引用,否则返回NULL。//示例:
PyObject* mymodule = PyImport_ImportModule("mymodule");
PyObject* myfunction = PyObject_GetAttrString(mymodule, "myfunction");
PyObject* args = PyTuple_New(1);
PyTuple_SetItem(args, 0, PyLong_FromLong(42));PyObject* result = PyObject_CallObject(myfunction, args);
if (result != NULL) {printf("Function returned: %ld\n", PyLong_AsLong(result));
} else {printf("Failed to call function.\n");
}
  • PyErr_Print 用于将当前错误信息打印到标准错误输出,方便调试程序。

2.python虚拟环境

2.1Python虚拟环境简介

virtualenv和anaconda都是用于创建Python虚拟环境的工具,二者的主要区别如下:

  1. 包管理器:virtualenv使用pip作为包管理器,而anaconda使用conda作为包管理器。
  2. 环境隔离:virtualenv只能隔离Python包,而anaconda可以隔离整个Python环境及其依赖项。
  3. 系统依赖:anaconda自带了许多科学计算所需的系统依赖,而virtualenv则需要手动安装这些依赖。
  4. 平台支持:anaconda支持Windows、Linux和MacOS等多个平台,而virtualenv则主要支持Linux和MacOS。

在这里选择virtualenv,原因是anaconda 在飞腾架构的麒麟系统上安装失败。

2.2 virtualenv 安装及使用

  • 1.安装
 sudo apt-get install pippip install virtualenv
  • 2.创建虚拟环境
cd /home/demo/bin/python
virtualenv demoEnv
#或者指定Python版本
virtualenv -p /usr/bin/python3.8 demoEnv
  • 3.激活虚拟环境
demoEnv\Scripts\activate
  • 4.安装依赖包
pip install -r requirements.txt
pip install python-docx
  • 5.退出虚拟环境
demoEnv\Scripts\deactivate

2.3 在C++程序中配置virtualenv 虚拟环境

demo程序利用了系统自带的Python3.8环境,所以在C++程序中只需配置好虚拟环境的包安装目录即可,这点是参考在终端通过命令执行Python脚本时的环境设置。例如执行下面的命令来查看当前Python环境的path内容:

python3 test.py
#其中 test.py 内容如下
import sys
print(sys.path)

因此Qt程序中Python环境初始化部分要增加设置Python虚拟环境安装包路径的代码,如下:

    QString modulePath = QString::fromLocal8Bit("sys.path.append('%1')").arg(qApp->applicationDirPath() + "/python/demoEnv/lib/python3.8/site-packages");PyRun_SimpleString(modulePath.toLocal8Bit().data());

经过上述设置就可以在虚拟环境中用pip命令安装应用程序所需的python包,并在应用程序所在目录的python文件中使用第三方包,如python-docx。当Qt程序需要发布到其他飞腾架构的麒麟V10设备上时,可以直接把虚拟环境一起打包,省去了在新的设备安装依赖包的步骤。

3.python-docx库的应用

官方参考文档https://python-docx.readthedocs.io
在这里插入图片描述
python-docx 作为word文档读写库算是很轻量了,其涉及的概念不多,很容易理解与掌握。下面是python-docx的一些核心概念。

  • Document 表示word文档。
  • Text 表示word文档中的文本和段落。
  • Section 表示页面布局,方向相同的页面。
  • Headers 、 Footers 表示页眉页脚
  • Table 表格
  • Image 图片

下面是一个快速上手指南:

  1. 打开一个word文档
from docx import Document
document = Document()
  1. 添加一个段落
paragraph = document.add_paragraph('Lorem ipsum dolor sit amet.')
或
prior_paragraph = paragraph.insert_paragraph_before('Lorem ipsum')
  1. 添加页眉
document.add_heading('The REAL meaning of the universe')
或
document.add_heading('The role of dolphins', level=2)
  1. 添加分页符
document.add_page_break()
  1. 添加表格
table = document.add_table(rows=2, cols=2)
cell = table.cell(0, 1)
cell.text = 'parrot, possibly dead'
row = table.rows[1]
row.cells[0].text = 'Foo bar to you.'
row.cells[1].text = 'And a hearty foo bar to you too sir!'
for row in table.rows:for cell in row.cells:print(cell.text)
row_count = len(table.rows)
col_count = len(table.columns)
row = table.add_row()
# get table data -------------
items = ((7, '1024', 'Plush kittens'),(3, '2042', 'Furbees'),(1, '1288', 'French Poodle Collars, Deluxe'),
)# add table ------------------
table = document.add_table(1, 3)# populate header row --------
heading_cells = table.rows[0].cells
heading_cells[0].text = 'Qty'
heading_cells[1].text = 'SKU'
heading_cells[2].text = 'Description'# add a data row for each item
for item in items:cells = table.add_row().cellscells[0].text = str(item.qty)cells[1].text = item.skucells[2].text = item.desc
table.style = 'LightShading-Accent1'
  1. 添加一个图片
document.add_picture('image-filename.png')
#设置图片尺寸
from docx.shared import Inches
document.add_picture('image-filename.png', width=Inches(1.0))

4.总结

以上就是本篇的所有内容了,关于python-docx应用的一些细节本文并未涉及太多,想要了解更多的话还是要阅读官方文档。对C++ python混合编程有疑问的朋友欢迎留言讨论!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/103602.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF中手写地图控件(3)——动态加载地图图片

瓦片增加一个Loading动画 可以查看我的另一个博客WPF中自定义Loading图 从中心扩散 进行从里到外的扩散&#xff0c;方向是上左下右。如下图所示 于是我们可以定义一个拥有坐标X跟Y的集合&#xff0c;他允许这个集合&#xff0c;内部使用枚举器的MoveNext自动排序&#xf…

文件容灾备份方案,软件容灾备份方案

信息是企业的核心资产。然而&#xff0c;信息数据丢失的风险接踵而至。事故系统异常、病毒攻击、硬件损坏和自然灾害都可能导致重要数据的丢失。这就是为什么文档灾难恢复备份计划如此重要。本文将详细介绍文档灾难恢复备份计划的必要性&#xff0c;以及如何实施有效的备份方案…

使用Nodejs搭建简单的HTTP服务器 - 内网穿透公网远程访问

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&…

LLM架构自注意力机制Transformers architecture Attention is all you need

使用Transformers架构构建大型语言模型显著提高了自然语言任务的性能&#xff0c;超过了之前的RNNs&#xff0c;并导致了再生能力的爆炸。 Transformers架构的力量在于其学习句子中所有单词的相关性和上下文的能力。不仅仅是您在这里看到的&#xff0c;与它的邻居每个词相邻&…

韦东山-电子量产工具项目:UI系统

代码结构 所有代码都已通过测试跑通&#xff0c;其中代码结构如下&#xff1a; 一、include文件夹 1.1 common.h #ifndef _COMMON_H #define _COMMON_Htypedef struct Region {int iLeftUpX; //区域左上方的坐标int iLeftUpY; //区域左下方的坐标int iWidth; //区域宽度…

如何在 Opera 中启用DNS over HTTPS

DNS over HTTPS&#xff08;基于HTTPS的DNS&#xff09;是一种更安全的浏览方式&#xff0c;但大多数 Web 浏览器默认情况下不启用它。了解如何在 Opera 浏览器中启用该功能。 您可能不知道这一点&#xff0c;但您的网络浏览器并不像您希望的那样私密或安全。您会看到&#xff…

搭建AI智能问答的这些前期工作可不要忘了

在搭建AI智能问答之前&#xff0c;我们需要做好相应的前期准备工作&#xff0c;不能盲目地去搭建模型。这样很容易导致我们模型后续的不完整性。所以looklook今天就基于搭建AI智能问答最基础的思路&#xff0c;带领大家一起去理顺一下我们需要做什么前期工作才能保证AI智能问答…

Web 开发 Django 管理工具

上次为大家介绍了 Django 的模型&#xff0c;通过模型就可以操作数据库&#xff0c;从而就可以改变页面的展示内容&#xff0c;那问题来了&#xff0c;我们只能通过手动编辑模型文件来配置模型吗&#xff1f;当然不是&#xff0c;Django 为我们提供了强大的工具&#xff0c;可以…

0101prox-shardingsphere-中间件

1 启动ShardingSphere-Proxy 1.1 获取 目前 ShardingSphere-Proxy 提供了 3 种获取方式&#xff1a; 二进制发布包DockerHelm 这里我们使用Docker安装。 1.2 使用Docker安装 step1&#xff1a;启动Docker容器 docker run -d \ -v /Users/gaogzhen/data/docker/shardings…

安装Node(脚手架)

目录 一&#xff0c;安装node&#xff08;脚手架&#xff09;1.1&#xff0c; 配置vue.config.js1.2&#xff0c; vue-cli3x的目录介绍1.3&#xff0c; package.json 最后 一&#xff0c;安装node&#xff08;脚手架&#xff09; 从官网直接下载安装即可&#xff0c;自带npm包管…

OpenCV基础知识(5)— 几何变换

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV中的几何变换是指改变图像的几何结构&#xff0c;例如大小、角度和形状等&#xff0c;让图像呈现出缩放、翻转、旋转和透视效果。这些几何变换操作都涉及复杂、精密的计算。OpenCV将这些计算过程都封装成了非常灵活的…

自动化编排工具Terraform介绍(一)

Terraform是什么&#xff1f;: Terraform 是 HashiCorp 公司旗下的 Provision Infrastructure 产品, 是 AWS APN Technology Partner 与 AWS DevOps Competency Partner。Terraform 是一个 IT 基础架构自动化编排工具&#xff0c;它的口号是“Write, Plan, and Create …

优化时间流:区间调度问题的探索与解决

在浩如烟海的信息时代&#xff0c;时间的有效管理成为了一门不可或缺的艺术。无论是生活中的琐事&#xff0c;还是工作中的任务&#xff0c;时间都在无声地流逝&#xff0c;挑战着我们的智慧。正如时间在日常生活中具有的宝贵价值一样&#xff0c;在计算机科学领域&#xff0c;…

3:Ubuntu上配置QT交叉编译环境并编译QT程序到Jetson Orin Nano(ARM)

1.Ubuntu Qt 配置交叉编译环境 1.1 ubuntu 20.04安装Qt sudo apt-get install qtcreator 1.2 配置QT GCC配置同上 最后配置Kits 上面设置完成之后 &#xff0c;设置Kits 中的Device(这是为了能够直接把项目部署到arm设备上) 点击NEXT之后会出现连接被拒绝&#xff0c;不用担…

USB Type-C端口集成式ESD静电保护方案 安全低成本

Type-C端口是根据USB3.x和USB4协议传输数据的&#xff0c;很容易受到电气过载&#xff08;EOS&#xff09;和静电放电&#xff08;ESD&#xff09;事件的影响。由于Type-C支持随意热插拔功能&#xff0c;其内部高集成度的芯片&#xff0c;更容易受到人体静电放电的伤害和损坏。…

Golang使用消息队列(RabbitMQ)

最近在使用Golang做了一个网盘项目&#xff08;类似百度网盘&#xff09;&#xff0c;这个网盘项目有一个功能描述如下&#xff1a;用户会删除一个文件到垃圾回收站&#xff0c;回收站的文件有一个时间期限&#xff0c;比如24h&#xff0c;24h后数据库中记录和oss中文件会被删除…

使用端口映射实现Spring Boot服务端接口的公网远程调试:详细配置与步骤解析

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

使用 Feature Flags 与可观测工具实现数据库灰度迁移

场景描述 很多企业会遇到数据库升级、或数据库迁移的情况&#xff0c;尤其是在自建数据库服务向云数据库服务、自建机房向云机房、旧数据库向新数据库迁移等场景。 然而&#xff0c;我们需要在整个移植过程中保证其稳定性、避免数据遗失、服务宕机等情况&#xff0c;最常见的移…

【Spring】一次性打包学透 Spring | 阿Q送书第五期

文章目录 如何竭尽可能确保大家学透Spring1. 内容全面且细致2. 主题实用且本土化3. 案例系统且完善4. 知识有趣且深刻 关于作者丁雪丰业内专家推图书热卖留言提前获赠书 不知从何时开始&#xff0c;Spring 这个词开始频繁地出现在 Java 服务端开发者的日常工作中&#xff0c;很…

BTP Integration Suite学习笔记 - (Unit4) Developing with SAP Integration Suite

详细指导还是要看官方文档 4. 云集成管理 4.1 云集成介绍 什么是云集成&#xff1f; 前三章讲了很多内容&#xff0c;但都不是最核心的&#xff0c;通常我们用CPI是让他实现原来PI/PO的功能的&#xff0c;是用来做集成的。这章才刚开始。 云集成有以下几个特性&#xff1a;…