logplus/app/fdsa4_test/pythonhandler.cpp

441 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pythonhandler.h"
#include <QCoreApplication>
#include <QFile>
#include <QProcessEnvironment>
PythonHandler::PythonHandler(QObject *parent)
: QObject(parent)
, m_initialized(false)
{
}
PythonHandler::~PythonHandler()
{
finalize();
}
PythonHandler *PythonHandler::getInstance()
{
static PythonHandler ref;
return &ref;
}
bool PythonHandler::initialize()
{
if (m_initialized) {
return true;
}
// 获取程序所在目录
QString appDir = QCoreApplication::applicationDirPath();
QString strPy= appDir + "/" + PYTHON_VER;
setupEnvironment(strPy);
strPy.toStdWString().c_str();
// 初始化Python解释器
Py_Initialize();
if (!Py_IsInitialized()) {
qDebug() << "Python初始化失败";
return false;
}
// 添加Python脚本路径 - 使用绝对路径会更可靠
QString currentPath = QCoreApplication::applicationDirPath();
QString scriptPath = currentPath + "/python_scripts";
// QString strPy= currentPath + "/" + PYTHON_VER;
// QString scriptPython2 = strPy + "/DLLs";
// QString scriptPython3 = strPy + "/Lib";
// QString scriptPython4 = strPy + "/lib/site-packages";
// emit addLog(scriptPath);
QString pythonCode = QString(
"import sys\n"
"import os\n"
"sys.path.append('%1')\n"
"print('========== Python 调试信息 ==========')\n"
"print('当前工作目录:', os.getcwd())\n"
"print('exepath:', sys.executable)\n"
"print('Python 搜索路径:')\n"
"for p in sys.path:\n"
" print(' -', p)\n"
"print('======================================')\n"
).arg(scriptPath);
// emit addLog(pythonCode);
PyRun_SimpleString(pythonCode.toStdString().c_str());
m_initialized = true;
return true;
}
void PythonHandler::setupEnvironment(QString strPy)
{
// 使用 Qt 的方式设置环境变量
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
// 设置 PYTHONHOME
qputenv("PYTHONHOME", strPy.toLocal8Bit());
// 设置 PYTHONPATH
QString pythonPath = strPy + "/Lib;" + strPy + "/lib/site-packages;" + strPy + "/DLLs;";
qputenv("PYTHONPATH", pythonPath.toLocal8Bit());
// 修改 PATH添加程序目录
QString currentPath = QString::fromLocal8Bit(qgetenv("PATH"));
QString newPath = strPy + "/DLLs;" + currentPath;
qputenv("PATH", newPath.toLocal8Bit());
qDebug() << "Environment:";
qDebug() << "PYTHONHOME:" << qgetenv("PYTHONHOME");
qDebug() << "PYTHONPATH:" << qgetenv("PYTHONPATH");
}
void PythonHandler::finalize()
{
if (m_initialized) {
Py_Finalize();
m_initialized = false;
}
}
PyObject* PythonHandler::qVariantToPythonObject(const QVariant &value)
{
switch (value.type()) {
case QVariant::Int:
return PyLong_FromLong(value.toInt());
case QVariant::Double:
return PyFloat_FromDouble(value.toDouble());
case QVariant::String:
return PyUnicode_FromString(value.toString().toStdString().c_str());
case QVariant::List: {
QVariantList list = value.toList();
PyObject* pyList = PyList_New(list.size());
for (int i = 0; i < list.size(); ++i) {
PyList_SetItem(pyList, i, qVariantToPythonObject(list[i]));
}
return pyList;
}
case QVariant::Bool:
return PyBool_FromLong(value.toBool() ? 1 : 0);
default:
return Py_None;
}
}
QVariant PythonHandler::pythonObjectToQVariant(PyObject *obj)
{
if (!obj) {
qDebug() << "pythonObjectToQVariant: 输入对象为NULL";
return QVariant();
}
qDebug() << "pythonObjectToQVariant: 转换类型" << Py_TYPE(obj)->tp_name;
if (PyLong_Check(obj)) {
long long value = PyLong_AsLongLong(obj);
if (PyErr_Occurred()) {
PyErr_Clear();
return QVariant();
}
qDebug() << "转换为整数:" << value;
return QVariant(value);
}
else if (PyFloat_Check(obj)) {
double value = PyFloat_AsDouble(obj);
qDebug() << "转换为浮点数:" << value;
return QVariant(value);
}
else if (PyBool_Check(obj)) {
bool value = (obj == Py_True);
qDebug() << "转换为布尔值:" << value;
return QVariant(value);
}
else if (PyUnicode_Check(obj)) {
QString value = QString::fromUtf8(PyUnicode_AsUTF8(obj));
qDebug() << "转换为字符串:" << value;
return QVariant(value);
}
else if (PyList_Check(obj)) {
QVariantList list;
Py_ssize_t size = PyList_Size(obj);
qDebug() << "转换为列表,大小:" << size;
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* item = PyList_GetItem(obj, i);
if (item) {
list.append(pythonObjectToQVariant(item));
} else {
list.append(QVariant());
}
}
return list;
}
else if (PyTuple_Check(obj)) {
QVariantList list;
Py_ssize_t size = PyTuple_Size(obj);
qDebug() << "转换为元组,大小:" << size;
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* item = PyTuple_GetItem(obj, i);
if (item) {
list.append(pythonObjectToQVariant(item));
} else {
list.append(QVariant());
}
}
return list;
}
else if (PyDict_Check(obj)) {
QVariantMap map;
PyObject* pKeys = PyDict_Keys(obj);
Py_ssize_t size = PyList_Size(pKeys);
qDebug() << "转换为字典,大小:" << size;
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* pKey = PyList_GetItem(pKeys, i);
PyObject* pValue = PyDict_GetItem(obj, pKey);
if (pKey && pValue && PyUnicode_Check(pKey)) {
QString key = QString::fromUtf8(PyUnicode_AsUTF8(pKey));
map[key] = pythonObjectToQVariant(pValue);
}
}
Py_DECREF(pKeys);
return map;
}
else if (obj == Py_None) {
qDebug() << "转换为None";
return QVariant();
}
else {
qDebug() << "未知类型返回空QVariant";
return QVariant();
}
}
QString PythonHandler::capturePythonError() {
QString errorMsg;
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
if (pvalue) {
PyObject* pstr = PyObject_Str(pvalue);
if (pstr) {
errorMsg = QString::fromUtf8(PyUnicode_AsUTF8(pstr));
#ifdef _RELEASE
Py_DECREF(pstr);
#endif
}
}
#ifdef _RELEASE
// 清理
Py_XDECREF(ptype);
Py_XDECREF(pvalue);
Py_XDECREF(ptraceback);
#endif
return errorMsg;
}
QVariant PythonHandler::executeScript(const QString &scriptPath,
const QString &functionName,
const QVariantList &args,
float* outAtt0all,
int nlen)
{
if (!m_initialized && !initialize()) {
return QVariant();
}
// 获取全局字典
PyObject* pModule = nullptr;
PyObject* pFunc = nullptr;
PyObject* pArgs = nullptr;
PyObject* pResult = nullptr;
QVariant result;
// 导入模块
QString moduleName = scriptPath;
if (moduleName.endsWith(".py")) {
moduleName.chop(3);
}
// pModule = PyImport_ImportModule("numpy");
// if (!pModule) {
// QString error = capturePythonError();
// qDebug() << "Python error:" << error;
//
// PyErr_Print();
// emit addLog("无法导入Python模块:" + moduleName);
// return QVariant();
// }
pModule = PyImport_ImportModule(moduleName.toStdString().c_str());
if (!pModule) {
QString error = capturePythonError();
qDebug() << "Python error:" << error;
//PyErr_Print();
emit addLog("无法导入Python模块:" + moduleName);
return QVariant();
}
// 获取函数
pFunc = PyObject_GetAttrString(pModule, functionName.toStdString().c_str());
if (!pFunc || !PyCallable_Check(pFunc)) {
if (PyErr_Occurred()) {
PyErr_Print();
}
emit addLog("无法找到函数:" + functionName);
Py_XDECREF(pFunc);
Py_DECREF(pModule);
return QVariant();
}
// 构建参数
pArgs = PyTuple_New(args.size());
for (int i = 0; i < args.size(); ++i) {
PyTuple_SetItem(pArgs, i, qVariantToPythonObject(args[i]));
}
// 调用函数
pResult = PyObject_CallObject(pFunc, pArgs);
if (pResult) {
if(outAtt0all)
{
PyObject* array1 = PyTuple_GetItem(pResult, 0);
double dR = PyFloat_AsDouble(PyTuple_GetItem(pResult, 1)); // 获取double
// // 将numpy数组转换为C++数组例如使用numpy的API
// PyArrayObject* arr1 = (PyArrayObject*)PyArray_FromAny(array1, NULL, 0, 0, NPY_ARRAY_CARRAY, NULL);
PyArrayObject* arr1 = (PyArrayObject*)array1;
double* data1 = (double*)PyArray_DATA(arr1);
int len = PyArray_DIM(arr1, 0); // 获取数组长度
if (len>nlen)
len = nlen;
for (int i = 0; i < len; i++) {
outAtt0all[i] = data1[i];
}
#ifdef _RELEASE
Py_DECREF(arr1);
#endif
}
else
{
result = pythonObjectToQVariant(pResult);
QMap<QString, QVariant> imgResult = result.toMap();
emit addLog("1#executeScript" + QString::number(imgResult.size()));
}
} else {
PyErr_Print();
emit addLog("函数调用失败");
}
#ifdef _RELEASE
// 清理
Py_XDECREF(pResult);
Py_XDECREF(pArgs);
Py_XDECREF(pFunc);
Py_XDECREF(pModule);
#endif
return result;
}
/*
QVariant PythonHandler::executeScript(const QString &scriptPath,
const QString &functionName,
const QVariantList &args)
{
if (!m_initialized && !initialize()) {
return QVariant();
}
// 获取全局字典
PyObject* pModule = nullptr;
PyObject* pFunc = nullptr;
PyObject* pArgs = nullptr;
PyObject* pResult = nullptr;
QVariant result;
// 导入模块
QString moduleName = scriptPath;
if (moduleName.endsWith(".py")) {
moduleName.chop(3);
}
pModule = PyImport_ImportModule(moduleName.toStdString().c_str());
if (!pModule) {
PyErr_Print();
emit addLog("无法导入Python模块:" + moduleName);
return QVariant();
}
// 获取函数
pFunc = PyObject_GetAttrString(pModule, functionName.toStdString().c_str());
if (!pFunc || !PyCallable_Check(pFunc)) {
if (PyErr_Occurred()) {
PyErr_Print();
}
emit addLog("无法找到函数:" + functionName);
Py_XDECREF(pFunc);
Py_DECREF(pModule);
return QVariant();
}
// 构建参数
pArgs = PyTuple_New(args.size());
for (int i = 0; i < args.size(); ++i) {
PyTuple_SetItem(pArgs, i, qVariantToPythonObject(args[i]));
}
// 调用函数
pResult = PyObject_CallObject(pFunc, pArgs);
if (pResult) {
result = pythonObjectToQVariant(pResult);
QMap<QString, QVariant> imgResult = result.toMap();
emit addLog("1#executeScript" + QString::number(imgResult.size()));
} else {
PyErr_Print();
emit addLog("函数调用失败");
}
#ifdef _RELEASE
// 清理
Py_XDECREF(pResult);
Py_XDECREF(pArgs);
Py_XDECREF(pFunc);
Py_XDECREF(pModule);
#endif
return result;
}
*/
QVariant PythonHandler::executeCode(const QString &code)
{
if (!m_initialized && !initialize()) {
return QVariant();
}
PyObject* pMain = PyImport_AddModule("__main__");
PyObject* pDict = PyModule_GetDict(pMain);
PyObject* pResult = PyRun_String(code.toStdString().c_str(),
Py_eval_input,
pDict,
pDict);
if (pResult) {
QVariant result = pythonObjectToQVariant(pResult);
Py_DECREF(pResult);
return result;
} else {
PyErr_Print();
return QVariant();
}
}