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 API
    Py_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.py
    PyObject *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 pip
 pip 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().cells
    cells[0].text = str(item.qty)
    cells[1].text = item.sku
    cells[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混合编程有疑问的朋友欢迎留言讨论!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于YOLOv8模型和PCB电子线路板缺陷目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型PCB电子线路板缺陷目标检测系统可用于日常生活中检测与定位PCB线路板瑕疵&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检…

panda3d加载模型复习和python面向对象编程属性学习

运行一个python示例&#xff1b;然后去除一些代码&#xff0c;只剩下加载模型相关&#xff0c;如下&#xff1b; from panda3d.core import loadPrcFileData # Configure the parallax mapping settings (these are just the defaults) loadPrcFileData("", "p…

Vue.js知识点学习的一点笔记

一、虚拟DOM 1、原生JS是命令式编程&#xff0c;当渲染在页面的数据发生一点点变化&#xff0c;需要整个重新渲染一编。vue.js渐进式框架有个虚拟DOM的概念&#xff0c;运用diff算法&#xff0c;比较新旧数据&#xff0c;相同的数据不变不重渲染&#xff0c;不同的部分新数据覆…

python 连接Redis 数据库

pip install redis python代码 import redis# 连接数据库 r redis.Redis(host192.168.56.15, port6379, db0)# 存储数据 #r.set(key, value) r.set(name, zaraNet)# 获取数据 value r.get(name) print(value)# 关闭连接&#xff08;可选&#xff09; r.close()

spring boot 整合mongodb

1、安装依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>2、配置数据库连接 spring:data:mongodb:host: localhostport: 27017username: xxxxxxp…

.fargo后缀勒索病毒|勒索病毒解密恢复|fargo勒索病毒解密|勒索病毒解密恢复|数据库恢复

fargo勒索病毒概述&#xff0c;fargo勒索病毒解密恢复及日常防护建议 目录&#xff1a; fargo勒索病毒介绍感染fargo勒索病毒后的表现fargo勒索病毒的感染形式如何恢复.fargo后缀勒索病毒fargo勒索病毒日常防护建议 简介&#xff1a; 河北某有限公司的财务系统&#xff0c;由…

拼多多商品详情API接入站点,实时数据json格式示例

作为国内最大的电商平台之一&#xff0c;拼多多数据采集具有多个维度。 有人需要采集商品信息&#xff0c;包括品类、品牌、产品名、价格、销量等字段&#xff0c;以了解商品销售状况、热门商品属性&#xff0c;进行市场扩大和重要决策&#xff1b; 商品数据&#xff1a;拼…

【数字实验室】时钟切换

大部分开发者使用 BUFGCTRL 或 BUFGMUX进行时钟切换&#xff0c;它们在时钟切换上可以提供无毛刺输出。然而&#xff0c;了解所涉及的原理是有好处的。 当然&#xff0c;无论我们在同步逻辑中使用哪种技术&#xff0c;重要的是要确保在进行时钟切换时输出上没有毛刺。任何故障都…

docker安装Oracle11gR2

文章目录 目录 文章目录 前言 一、前期准备 二、具体配置 2.1 配置oracle容器 2.2 配置navicat连接 总结 前言 使用docker模拟oracle环境 一、前期准备 安装好docker #拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g #启动 docker run -…

YOLOv5改进系列(22)——替换主干网络之MobileViTv1(一种轻量级的、通用的移动设备 ViT)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

安防监控/视频集中存储/云存储平台EasyCVR v3.3增加首页告警类型

安防监控/视频集中存储/云存储EasyCVR视频汇聚平台&#xff0c;可支持海量视频的轻量化接入与汇聚管理。平台能提供视频存储磁盘阵列、视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联、H.265自动转码等…

亚马逊搜索关键词下单怎么操作

亚马逊鲲鹏系统可以根据产品关键词搜索后进行下单购买&#xff0c;多个亚马逊买家号搜索关键词下单可以帮助关键词上首页&#xff0c;具体操作如下&#xff1a; 首先需要先准备好一批能下单的买家账号及代理ip&#xff0c;准备好之后就可以设置需要下单的关键词及asin进行货比…

Navicat 蝉联 2023年度 DBTA 读者选择奖的“最佳数据库管理员解决方案”奖项和 DBTA 100 强名单

近日&#xff0c;Database Trends and Applications (简称 DBTA) 颁发的“读者选择奖”获奖名单新鲜出炉&#xff0c;Navicat 蝉联 2023 年度 DBTA 读者选择奖的“最佳数据库管理员&#xff08;DBA&#xff09;解决方案”奖项和 DBTA 100 强名单&#xff0c;我们感到无比荣幸和…

AutoHotkey:定时删除目录下指定分钟以前的文件,带UI界面

删除指定目录下&#xff0c;所有在某个指定分钟以前的文件&#xff0c;可以用来清理经常生成很多文件的目录&#xff0c;但又需要保留最新的一部分文件 支持拖放目录到界面 能够记忆设置&#xff0c;下次启动后不用重新设置&#xff0c;可以直接开始 应用场景比如&#xff1a…

Python制作爱心并打包成手机端可执行文件

前言 本文是想要将python代码打包成在手机上能执行的文件 尝试了几个库&#xff0c; 有这也那样的限制&#xff0c;最终还是选了BeeWare 环境&#xff1a;python3.7.x 开始 找到打包有相关工具os-android-apk-builder&#xff0c;buildozer&#xff0c;cx_Freeze&#xff…

三、Kafka生产者

目录 3.1 生产者消息发送流程3.1.1 发送原理 3.2 异步发送 API3.3 同步发送数据3.4 生产者分区3.4.1 kafka分区的好处3.4.2 生产者发送消息的分区策略3.4.3 自定义分区器 3.5 生产者如何提高吞吐量3.6 数据可靠性 3.1 生产者消息发送流程 3.1.1 发送原理 3.2 异步发送 API 3…

uniapp 顶部头部样式

<u-navbartitle"商城":safeAreaInsetTop"true"><view slot"left"><image src"/static/logo.png" mode"" class"u-w-50 u-h-50"></image></view></u-navbar>

深入了解 Java 中 Files 类的常用方法及抽象类的 final 修饰

文章目录 Files 类常用方法抽象类的 final 修饰 &#x1f389;欢迎来到Java学习路线专栏~深入了解 Java 中 Files 类的常用方法及抽象类的 final 修饰 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;该系列文章专栏&#xff1a…

JetBrains IDE远程开发功能可供GitHub用户使用

JetBrains与GitHub去年已达成合作&#xff0c;提供GitHub Codespaces 与 JetBrains Gateway 之间的集成。 GitHub Codespaces允许用户创建安全、可配置、专属的云端开发环境&#xff0c;此集成意味着您可以通过JetBrains Gateway使用在 GitHub Codespaces 中运行喜欢的IDE进行…

数字化赋能高质量施工,成企业创新转型新方向

建筑行业是一个需要投入大量资金、能源消耗大、风险高且劳动力密集的行业&#xff0c;传统施工管理方式存在着“无法实时控制进度、无法实时控制质量、材料浪费、常需返工、安全事件频发”等问题。 为了自身的转型升级&#xff0c;也为了响应国家战略规划落地对建筑行业提出的要…