《QT從基礎到進階·七十四》Qt+C++開發一個python編譯器,能夠編寫,運行python程序改進版

1、概述
源碼放在文章末尾

根據上一篇文章回顧下利用Qt+C++實現了一個簡易的python編譯器,類似pycharm或vsCode這樣的編譯器,該python編譯器目前實現了如下功能:
(1)支持編寫python程序
(2)編寫代碼時有代碼補全提示
(3)程序運行到每行時該行高亮顯示
(4)可以加載python腳本執行
(5)可以在程序運行的過程中隨時中斷
(6)有輸出窗口實時顯示程序執行的狀態或執行程序的打印顯示等

詳細介紹可以看我上一篇文章。

在這篇文章中對上一版代碼進行了一些優化和修改,具體修改功能如下:
(1)美化了界面操作,更像一個簡易的python編譯器
(2)新增了代碼斷點調試功能
(3)新增了菜單欄,功能分別為一鍵加載python腳本、運行python腳本、停止運行、單步調試、連續調試、清空所有斷點,如下所示
在這里插入圖片描述

下圖為Python編譯器的demo演示流程:
1、一鍵加載python腳本
在這里插入圖片描述
關鍵代碼如下所示(注意:加載python腳本時不能有中文路徑,不然無法識別):

void pythonRecipeWidget::on_loadScriptPushButton_clicked()
{QString initialDir;QString filePath = QFileDialog::getOpenFileName(this, tr("Select Script"), initialDir);if (filePath.isEmpty())return;ui.scriptPlainTextEdit->clear();std::ifstream file(filePath.toStdString());std::string script((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());ui.scriptPlainTextEdit->setPlainText(script.c_str());file.close();
}

2、運行python腳本
給的例子中的python腳本會運行完for循環然后繼續往下運行時會正常報錯,因為沒有導入該第三方工作庫
在這里插入圖片描述

3、停止運行
在這里插入圖片描述

4、斷點單步調試
在這里插入圖片描述

5、連續調試
在這里插入圖片描述

6、清除所有斷點
在這里插入圖片描述

主要代碼分析:
運行 Python 腳本:使用 PyRun_SimpleString。

設置斷點:通過 MyTrace 回調攔截 PyTrace_LINE。

斷點調試(斷點、暫停、繼續、單步執行)。

中斷機制(用戶手動終止腳本)。

線程安全處理(QtConcurrent::run + PyGILState_Ensure)。

UI 控制啟用/禁用(通過 QMetaObject::invokeMethod)。

QtConcurrent::run([=](){qDebug() << __FUNCTION__ << QThread::currentThreadId() << QThread::currentThread();QMetaObject::invokeMethod(m_run, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false));QMetaObject::invokeMethod(m_stop, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, true));QMetaObject::invokeMethod(m_stepOver, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, true));QMetaObject::invokeMethod(m_continueExecute, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, true));PyGILState_STATE gstate = PyGILState_Ensure();scriptThreadState = PyThreadState_Get();PyEval_SetTrace(MyTrace, NULL);PyRun_SimpleString(GBK_To_UTF8(g_script).c_str());scriptThreadState = nullptr;PyGILState_Release(gstate);QMetaObject::invokeMethod(m_run, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, true));QMetaObject::invokeMethod(m_stop, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false));QMetaObject::invokeMethod(m_stepOver, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false));QMetaObject::invokeMethod(m_continueExecute, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false));is_paused = false;step_once = false;});

在后臺線程中運行 Python 腳本,確保線程間 GIL 安全。

scriptThreadState 保存當前線程狀態,供中斷使用。

設置了 MyTrace 作為追蹤函數,實現在某些行/事件進行控制,MyTrace實現對代碼的斷點、停止、繼續運行等功能

int MyTrace(PyObject* obj, PyFrameObject* frame, int what, PyObject* arg)
{if (g_isExection)return 0;//如果把中斷程序放在這里會導致比如在第二行中斷時會在第二行執行完才中斷if ((lineCount == PyFrame_GetLineNumber(frame)) && what == PyTrace_EXCEPTION){g_isExection = true;int line = PyFrame_GetLineNumber(frame);return 0;}if (what == PyTrace_LINE){char const* fileName = _PyUnicode_AsString(frame->f_code->co_filename);char const* name = _PyUnicode_AsString(frame->f_code->co_name);if (strcmp(fileName, "<string>") == 0 && strcmp(name, "__new__") != 0){int line = PyFrame_GetLineNumber(frame);lineCount = line;ShowLine(line);qDebug() << "filename" << fileName << "name" << name << "line" << line << "frame" << frame << "f_back" << frame->f_back;breakPointAfter = line;//如果斷點不在代碼行上就移到下面最近的代碼行for (auto breakPointLine : breakPoints){if (breakPointBefore < breakPointLine && breakPointLine < breakPointAfter){breakPointCallBack_(breakPointBefore, breakPointAfter);is_paused = true;step_once = false;breakPointBefore = line;break;}}//當前代碼行等于斷點行就暫停程序if (breakPointAfter != breakPointBefore){for (auto breakPointLine : breakPoints){if (line == breakPointLine){is_paused = true;step_once = false;break;}}}breakPointBefore = line;//判斷當前是否debuggingif (is_paused && !step_once)bpDebuggingLineCallBack_(line, true);elsebpDebuggingLineCallBack_(line, false);// 暫停執行,等待繼續調試信號while (is_paused && !step_once) {std::this_thread::sleep_for(std::chrono::milliseconds(100));}// 單步執行一次后繼續暫停if (step_once) {is_paused = true;step_once = false;}//如果把中斷程序放在這里會導致比如在第二行中斷時會在第二行執行前中斷if (g_isAbort){if (!m_isInterrupt){qDebug() << "User abort.";//PyErr_SetString(PyExc_KeyboardInterrupt, "User abort.");if (scriptThreadState){PyGILState_STATE gstate = PyGILState_Ensure();PyThreadState_SetAsyncExc((unsigned long)scriptThreadState->thread_id, PyExc_KeyboardInterrupt);PyGILState_Release(gstate);}m_isInterrupt = true;}bpDebuggingLineCallBack_(line, false);return 0;}}}return 0;
}

追蹤函數 MyTrace
追蹤函數通過判斷 what == PyTrace_LINE 來對 Python 腳本執行的每一行做攔截,并根據斷點及狀態決定:

for (auto breakPointLine : breakPoints)
{if (line == breakPointLine){is_paused = true;step_once = false;break;}
}

命中斷點:暫停程序。

ShowLine(line) 和 bpDebuggingLineCallBack_() 用于 UI 更新。

單步執行邏輯

while (is_paused && !step_once) {std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

is_paused 和 step_once 控制主調試循環。

外部通過點擊 “繼續” 或 “單步” 按鈕控制 is_paused 和 step_once 變量。

中斷處理(abort)

if (g_isAbort && !m_isInterrupt)
{PyThreadState_SetAsyncExc((unsigned long)scriptThreadState->thread_id, PyExc_KeyboardInterrupt);m_isInterrupt = true;
}

用戶點擊“停止”按鈕時觸發中斷。

使用 PyThreadState_SetAsyncExc 強行注入 KeyboardInterrupt 異常。

斷點跳轉優化

if (breakPointBefore < breakPointLine && breakPointLine < breakPointAfter)

源碼下載

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/900440.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900440.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900440.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Winform MQTT客戶端連接方式

項目中使用到Winform的數據轉發服務&#xff0c;所以記錄下使用到的方法。 一.創建單例模板 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp.Scripts {public class SingleTon&…

Windows強制刪除任何你想刪除的文件和文件夾

Windows強制刪除任何你想刪除的文件和文件夾 本教程適用于 Windows 10/11 系統&#xff0c;工具和命令均經過驗證。 為什么刪除會失敗&#xff1f; 權限不足&#xff1a;文件或文件夾可能需要管理員權限才能刪除。文件被占用&#xff1a;某個程序正在使用目標文件&#xff0c…

Jmeter如何使用MD5進行加密?

在軟件測試中&#xff0c;使用 JMeter 對數據進行 MD5 加密是一項常見需求&#xff0c;尤其是在模擬用戶登錄等涉及密碼加密的場景時。下面詳細介紹在 JMeter 里運用 MD5 加密的具體步驟。 1. 添加 BeanShell 預處理器 JMeter 本身沒有直接的 MD5 加密功能&#xff0c;但可以…

4-c語言中的數據類型

一.C 語?中的常量 1.生活中的數據 整數&#xff1a; 100,200,300,400,500 小數: 11.11 22.22 33.33 字母&#xff1a; a&#xff0c;b&#xff0c;c&#xff0c;d A&#xff0c;B&#xff0c;C&#xff0c;D 在 C 語?中我們把字?叫做字符. 字符?單引號引?。例如A’ 單詞…

中鈞科技通過數字賦能,編織“數字互聯網”助力數字化進程!

時間飛逝轉眼間2025年已過去四分之一&#xff0c;作為一名95后回顧當下的生活&#xff0c;忍不住感慨10年和現在的對比。發現現在的手機支付、網上掛號、APP打車、在線學習、網絡訂餐、線上協同辦公都以逐漸成為人們生活、工作的常態。也正是在這樣的常態背景下&#xff0c;加快…

AI重塑云基礎設施,亞馬遜云科技打造AI定制版IaaS“樣板房”

AI正在徹底重塑云基礎設施。 IDC最新《2025年IDC MarketScape&#xff1a;全球公有云基礎設施即服務&#xff08;IaaS&#xff09;報告》顯示&#xff0c;AI正在通過多種方式重塑云基礎設施&#xff0c;公有云IaaS有望繼續保持快速增長&#xff0c;預計2025年全球IaaS的整體規…

高效深度學習lecture01

lecture01 零樣本學習(Zero-Shot Learning, ZSL)&#xff1a; 模型可以在沒有見過某種特定任務或類別的訓練樣本的情況下&#xff0c;直接完成對應的任務 利用知識遷移 模型在一個任務上訓練時學到的知識&#xff0c;能夠遷移到其他任務上比如&#xff0c;模型知道“狗”和“…

使用 iPerf 測試內網兩臺機器之間的傳輸速度

在現代網絡管理中&#xff0c;確保內部網絡&#xff08;內網&#xff09;的高效運行是至關重要的。為了評估和優化網絡性能&#xff0c;我們需要一種可靠的方法來測試內網中不同設備間的傳輸速率。iPerf 作為一款廣泛使用的工具&#xff0c;能夠幫助我們準確測量兩個節點之間的…

視頻設備軌跡回放平臺EasyCVR如何搭建公共娛樂場所遠程視頻監控系統

一、背景介紹 由于KTV、酒吧、足療店等服務場所人員流動頻繁、環境復雜&#xff0c;一直是治安管理的重點區域。為有效打擊 “黃賭毒”、打架斗毆、尋釁滋事等違法犯罪的活動&#xff0c;打造安全有序的娛樂消費環境&#xff0c;我國相關部門將加大對這類場所的清查與管控力度…

vue進度條組件

<div class"global-mask" v-if"isProgress"><div class"contentBox"><div class"progresstitie">數據加載中請稍后</div><el-progress class"progressStyle" :color"customColor" tex…

Css:如何解決絕對定位子元素內容被父級元素overflow:hidden屬性剪裁

一、問題描述 今天小伙伴提了一個bug&#xff0c;在點擊列表項的“…”按鈕應該出現的懸浮菜單顯示不完整&#xff1a; 二、問題排查 一般這種問題&#xff0c;是由于懸浮菜單采用的是絕對定位&#xff0c;而父級采用了overflow:hidden屬性。但需要注意的是&#xff0c;這里的…

JavaScript基礎--01-JS簡介

字面量&#xff1a;數字、字符串、布爾值 前言JavaScript背景Web前端有三層&#xff1a;發展歷史JavaScript的發展&#xff1a;蒸蒸日上 JavaScript介紹JavaScript入門易學性JavaScript是腳本語言JavaScript的組成 JavaScript 的特點特點1&#xff1a;解釋型語言特點2&#xff…

[leetcode] 面試經典 150 題——篇9:二叉樹(番外:二叉樹的遍歷方式)

二叉樹的遍歷是指按照某種順序訪問二叉樹中的每個節點。常見的遍歷方式有四種&#xff1a;前序遍歷&#xff08;Pre-order Traversal&#xff09;、中序遍歷&#xff08;In-order Traversal&#xff09;、后序遍歷&#xff08;Post-order Traversal&#xff09;以及層序遍歷&am…

es基本概念

Elasticsearch 的架構與基本概念 Elasticsearch&#xff08;簡稱 ES&#xff09;是一個開源的分布式搜索和分析引擎&#xff0c;基于 Apache Lucene 構建。它被廣泛用于全文搜索、日志分析、實時數據分析等場景。以下是其架構概述及其基本概念的詳細解釋。 Elasticsearch 的架…

《星環之城:量子迷霧下的網絡安全戰記》

點擊下面圖片帶您領略全新的嵌入式學習路線 &#x1f525;爆款熱榜 88萬閱讀 1.6萬收藏 序章&#xff1a;星環之隕 公元2145年&#xff0c;人類在火星軌道上建造了“星環之城”——一座由量子網絡連接的太空城邦。它的中樞AI“蓋婭”掌控著地球與殖民地的數據洪流&#xff…

《全棧+雙客戶端Turnkey方案》架構設計圖

今天分享一些全棧雙客戶端Turnkey方案的架構與結構圖。 1&#xff1a;三種分布式部署方案:網關方案&#xff0c;超級服務器單服方案&#xff0c;直連邏輯服方案 2: 單服多線程核心架構: 系統服務邏輯服服務 3: 系統服務的多線程池調度設計 4:LogicServer Update與ECS架構&…

打破界限:Android XML與Jetpack Compose深度互操作指南

在現有XML布局項目中逐步引入Jetpack Compose是現代Android開發的常見需求。本指南將全面介紹混合使用的最佳實踐、技術細節和完整解決方案。 一、基礎配置 1.1 Gradle配置 android {buildFeatures {compose true}composeOptions {kotlinCompilerExtensionVersion "1.5.3…

React-narice安卓打包流程

**1. 生成簽名密鑰 在項目的 android/app 目錄下生成簽名密鑰的步驟&#xff1a; 打開終端或命令提示符&#xff1a;導航到您的 React Native 項目的 android/app 目錄。 運行以下命令生成密鑰庫文件&#xff1a; keytool -genkeypair -v -keystore my-release-key.keystor…

嵌入式AI開源生態指南:從框架到應用的全面解析

嵌入式AI開源生態指南&#xff1a;從框架到應用的全面解析 引言 隨著人工智能技術的迅速發展&#xff0c;將AI能力部署到邊緣設備上的需求日益增長。嵌入式AI通過在資源受限的微控制器上運行機器學習模型&#xff0c;實現了無需云連接的本地智能處理&#xff0c;大幅降低了延…

深度學習中模型量化那些事

在深度學習中模型量化可以分為3塊知識點&#xff0c;數據類型、常規模型量化與大模型量化。本文主要是對這3塊知識點進行淺要的介紹。其中數據類型是模型量化的基本點。常規模型量化是指對普通小模型的量化實現&#xff0c;通常止步于int8的量化&#xff0c;絕大部分推理引擎都…