慈溪市建设局网站表格下载,设计网单,昆山人才网官网,开发软件定制目录 前言1.C调用python1.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.总结 前言 … 目录 前言1.C调用python1.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.81.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虚拟环境的工具二者的主要区别如下
包管理器virtualenv使用pip作为包管理器而anaconda使用conda作为包管理器。环境隔离virtualenv只能隔离Python包而anaconda可以隔离整个Python环境及其依赖项。系统依赖anaconda自带了许多科学计算所需的系统依赖而virtualenv则需要手动安装这些依赖。平台支持anaconda支持Windows、Linux和MacOS等多个平台而virtualenv则主要支持Linux和MacOS。
在这里选择virtualenv原因是anaconda 在飞腾架构的麒麟系统上安装失败。
2.2 virtualenv 安装及使用
1.安装 sudo apt-get install pippip install virtualenv2.创建虚拟环境
cd /home/demo/bin/python
virtualenv demoEnv
#或者指定Python版本
virtualenv -p /usr/bin/python3.8 demoEnv3.激活虚拟环境
demoEnv\Scripts\activate4.安装依赖包
pip install -r requirements.txt
pip install python-docx5.退出虚拟环境
demoEnv\Scripts\deactivate2.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 图片
下面是一个快速上手指南
打开一个word文档
from docx import Document
document Document()添加一个段落
paragraph document.add_paragraph(Lorem ipsum dolor sit amet.)
或
prior_paragraph paragraph.insert_paragraph_before(Lorem ipsum)添加页眉
document.add_heading(The REAL meaning of the universe)
或
document.add_heading(The role of dolphins, level2)添加分页符
document.add_page_break()添加表格
table document.add_table(rows2, cols2)
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添加一个图片
document.add_picture(image-filename.png)
#设置图片尺寸
from docx.shared import Inches
document.add_picture(image-filename.png, widthInches(1.0))4.总结
以上就是本篇的所有内容了关于python-docx应用的一些细节本文并未涉及太多想要了解更多的话还是要阅读官方文档。对C python混合编程有疑问的朋友欢迎留言讨论