You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用exec执行含类继承的PyQt代码片段时出现作用域相关报错

问题原因及修复方案

问题根源

报错完全由exec()的作用域规则导致:

  • 全局作用域调用exec()时,执行产生的所有类、变量都会存入全局命名空间,Test类__init__方法调用super(Test, self)时可以正常在全局作用域找到Test类定义,运行正常。
  • 在keyPressEvent实例方法的局部作用域调用exec()时,默认会把执行产生的所有名称存入当前方法的局部命名空间(locals()),而Python类内部方法运行时不会向上查找外层函数的局部作用域,因此__init__里的super(Test, self)找不到Test类定义,触发NameError。多次执行时局部命名空间残留的旧类定义还会导致类类型不匹配,触发super()的TypeError。

修复方案

只需要修改keyPressEvent中的exec调用语句,主动指定执行的全局命名空间即可,两种可选方案:

方案1:直接使用主程序全局命名空间

和全局作用域执行效果完全一致,修改代码为:

exec(self.toPlainText(), globals())

方案2:使用独立命名空间(推荐,避免污染主程序变量)

如果不想让执行代码的变量覆盖主程序的全局变量,可创建独立字典作为执行上下文的全局命名空间:

# 创建独立的执行上下文,所有执行产生的变量都存在该字典中
exec_context = {}
exec(self.toPlainText(), exec_context)

完整修改后的keyPressEvent代码示例

def keyPressEvent(self, event):
    if event.modifiers() == Qt.ControlModifier:
        if event.key() == Qt.Key_Return:
            # 两种方案二选一即可
            # 方案1
            exec(self.toPlainText(), globals())
            # 方案2
            # exec_context = {}
            # exec(self.toPlainText(), exec_context)
    return QPlainTextEdit.keyPressEvent(self, event)

注:原来注释的exec(compile(self.toPlainText(), "script", "exec"), globals(), locals())同样会报错,原因是显式指定了局部命名空间为locals(),类定义还是会被存入局部作用域。

内容的提问来源于stack exchange,提问作者Emmuh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 01:42:03