关于 pyside6-reviewer
面向现代 PySide6 和 Qt 6.8+ 应用的代码审查技能,供审查者检查线程、信号槽、模型、资源生命周期、异步代码和 QML 集成,并提供参考资料与 PR 清单。
主要功能
- 01检查 Qt 6.8+ 兼容性
- 02审查线程安全
- 03验证信号与槽
- 04检查模型/视图和 QML
- 05审查资源与异步模式
- 06提供参考资料和 PR 清单
适用场景
- 01审查 PySide6 拉取请求
- 02查找跨线程 GUI 访问风险
- 03检查信号与槽签名
- 04评估模型/视图或 QML 代码
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ akiselev/ qt-llm-template --skill pyside6-reviewer安装后在 Claude Code 中输入/pyside6-reviewer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
anti-patterns.mdmodel-view.mdperformance.mdqml-integration.mdreview.pysignals-slots.mdthreading.mdwidgets.md详细介绍
PySide6 代码审查
针对现代 PySide6/Qt 6.8+ 应用的专业代码审查。
审查流程
- 确认 Qt 版本假设 — 验证代码面向 Qt 6.8+(不兼容 Qt5)
- 检查线程安全 — 所有 GUI 操作都在主线程上执行,并采用正确的工作线程模式
- 验证信号/槽用法 — 使用现代连接语法,并确保签名正确
- 评估 Model/View 实现 — 检查角色用法、数据方法模式和索引有效性
- 检查资源管理 — 检查父子所有权,防止泄漏
- 评估异步模式 — 检查 QThread、QtConcurrent、asyncio 集成
- 检查 QML 集成 — 检查属性绑定、类型注册和上下文公开
必须指出的关键反模式
# WRONG: GUI operation from worker thread
class Worker(QThread):
def run(self):
self.label.setText("Done") # CRASH: Cross-thread GUI access
# WRONG: Blocking the event loop
def on_button_click(self):
time.sleep(5) # FREEZES UI
requests.get(url) # FREEZES UI
# WRONG: Old-style signal connection (Qt4/5 legacy)
self.connect(button, SIGNAL("clicked()"), self.handler)
# WRONG: String-based slot connection
button.clicked.connect("self.handler") # Should be callable
# WRONG: No parent = memory leak risk
label = QLabel("text") # Should have parent or be assigned to layout
# WRONG: Deleting QObject while signals pending
obj.deleteLater() # OK
del obj # WRONG if signals/slots active
# WRONG: Direct widget manipulation in QThread.run()
class BadWorker(QThread):
def run(self):
self.progress_bar.setValue(50) # Thread violation!
必须采用的现代模式
信号/槽连接
# Qt 6 style - always use this
button.clicked.connect(self.on_click)
button.clicked.connect(lambda: self.handler(arg))
# Typed signals with modern syntax
class Worker(QObject):
progress = Signal(int) # Single type
result = Signal(str, list) # Multiple types
error = Signal(Exception) # Exception passing
finished = Signal() # No arguments
线程安全的工作线程模式
class Worker(QObject):
finished = Signal()
progress = Signal(int)
result = Signal(object)
error = Signal(str)
@Slot()
def run(self):
try:
for i in range(100):
# Do work
self.progress.emit(i)
self.result.emit(data)
except Exception as e:
self.error.emit(str(e))
finally:
self.finished.emit()
# Usage
thread = QThread()
worker = Worker()
worker.moveToThread(thread)
thread.started.connect(worker.run)
worker.finished.connect(thread.quit)
worker.finished.connect(worker.deleteLater)
thread.finished.connect(thread.deleteLater)
thread.start()
异步集成(Qt 6.8+)
import asyncio
from PySide6.QtAsyncio import QAsyncioEventLoopPolicy
# Set up asyncio with Qt event loop
asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())
class AsyncWidget(QWidget):
async def fetch_data(self):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
def start_fetch(self):
asyncio.ensure_future(self.fetch_data())
详细参考文件
- references/signals-slots.md — 信号/槽模式、连接类型、线程安全的信号发射
- references/model-view.md — QAbstractItemModel、角色、代理、委托
- references/threading.md — QThread、QtConcurrent、异步模式、线程池
- references/widgets.md — Widget 生命周期、布局、样式、高 DPI
- references/qml-integration.md — QML/Python 桥接、属性、类型注册
- references/performance.md — 绘制优化、模型效率、延迟加载
- references/anti-patterns.md — 完整的反模式目录及修复方法
审查清单(用于 PR)
线程安全
- 所有 widget/GUI 调用仅在主线程上执行
- 工作线程使用信号/槽更新 UI
- 主线程中没有
time.sleep()或阻塞调用 -
QThread子类仅重写run(),不在构造函数中执行工作 - 正确使用
moveToThread()(对象没有父对象)
内存管理
- Widget 有父对象,或已添加到布局中
- 对 QObject 使用
deleteLater(),绝不使用del - Lambda 连接不会捕获过期引用
- 避免循环信号连接
- 模型数据按值而非按引用返回
信号/槽正确性
- 使用现代连接语法(不使用字符串)
- 信号签名与槽签名匹配
- 所有槽都使用
@Slot()装饰器 - 跨线程信号使用
Qt.QueuedConnection - 信号定义为类属性
Model/View
- 使用
beginInsertRows()/endInsertRows()包围更改操作 - 更新时发射
dataChanged - 访问前检查
index.isValid() - 自定义角色使用
Qt.UserRole + n - 为兼容 QML 重写
roleNames()
性能
- 不在绘制事件中创建 widget
- 重绘时使用
update(),而非repaint() - 大型列表使用 QAbstractItemModel(而非 QListWidget)
- 对开销较大的数据进行延迟加载
- 批量更新期间使用
blockSignals()
Qt 6.8+ 特性
- 使用新的枚举作用域(
Qt.AlignmentFlag.AlignCenter) - 异步模式使用
QtAsyncio(而非第三方库) - 使用
QML_ELEMENT宏对应的方式注册类型 - 适用时通过
QProperty进行属性绑定 - 使用新的
QPermissionAPI 管理平台权限
评论
支持 Markdown