logplus/app/fdsa4_test/pythonhandler.cpp

345 lines
10 KiB
C++
Raw Normal View History

#include "pythonhandler.h"
#include <QCoreApplication>
#include <QFile>
#include <QProcessEnvironment>
PythonHandler::PythonHandler(QObject *parent)
: QObject(parent)
, m_initialized(false)
{
// 初始化Python
if (!this->initialize()) {
qDebug() << "Python初始化失败";
}
}
PythonHandler::~PythonHandler()
{
finalize();
}
PythonHandler *PythonHandler::getInstance()
{
static PythonHandler ref;
return &ref;
}
bool PythonHandler::initialize()
{
if (m_initialized) {
return true;
}
setupEnvironment();
// 初始化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"
"print('Python_:', sys.path)\n"
"sys.path.append('%1')\n"
"sys.path.append('%2')\n"
"sys.path.append('%3')\n"
"sys.path.append('%4')\n"
"sys.path.append('%5')\n"
"sys.path.append('%6')\n"
"print('end_:', sys.path)\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(currentPath).arg(scriptPath)
.arg(strPy).arg(scriptPython2).arg(scriptPython3).arg(scriptPython4);
// emit addLog(pythonCode);
PyRun_SimpleString(pythonCode.toStdString().c_str());
m_initialized = true;
return true;
}
void PythonHandler::setupEnvironment()
{
// 获取程序所在目录
QString appDir = QCoreApplication::applicationDirPath();
// 使用 Qt 的方式设置环境变量
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
// 设置 PYTHONHOME
qputenv("PYTHONHOME", appDir.toLocal8Bit());
QString strPy= appDir + "/" + PYTHON_VER;
// 设置 PYTHONPATH
QString pythonPath = strPy + "/Lib;" + strPy + "/DLLs;" + strPy + "/python_scripts";
qputenv("PYTHONPATH", pythonPath.toLocal8Bit());
// 修改 PATH添加程序目录
QString currentPath = QString::fromLocal8Bit(qgetenv("PATH"));
QString newPath = appDir + ";" + strPy + "/DLLs;" + currentPath;
qputenv("PATH", newPath.toLocal8Bit());
qDebug() << "环境变量已设置:";
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();
}
}
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(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) {
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::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();
}
}