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

PySide6打包Mac应用时窗口闪退无法输入问题求助

问题:PySide6打包Mac应用闪退,无法输入

我有一个功能正常的Python成绩计算程序,能接收作业名称、日期、分数及占比等输入并计算总分,输入逻辑适配我校网站格式。现在尝试用PySide6把它打包成Mac应用,但运行时窗口弹出后立刻闪退,根本没法输入。下面是原程序代码和我写的PySide6代码:

原程序代码

raw_grade = []
indexes = []
index = 0
score = []
percent = []
fi_score = []
raw = []
add = 0
denom = 0
total = 0
import sys
import re
from operator import itemgetter
print("Enter the data")

def multi_input():
    try:
        while True:
            data=input()
            if not data: break
            yield data
    except KeyboardInterrupt:
        return

data = list(multi_input())

for i in range(3, len(data),4):
    index = i
    indexes.append(i)

raw_grade = [data[id] for id in indexes]

for i in range(len(raw_grade)):
    gc = raw_grade[i].split('\t')
    raw.append(gc)

for i in range(len(raw)):
    percent.append(raw[i][3])
    score.append(raw[i][4])

for i in range(len(score)):
    use_score = score[i].split('/')
    fi_score.append(use_score)

score = fi_score

score = [value for value in score if value != ['']]


for i in range(len(score)):
    score[i] = [float(i) for i in score[i]]

for i in range(len(score)):
    try:
        score[i] = score[i][0]/score[i][1]*100
    except ZeroDivisionError:
        result = 0

for i in range(len(percent)):
    try:
        percent[i] = percent[i].replace('%', '')
    except ZeroDivisionError:
        result = 0

percent = [value for value in percent if value != '']

for i in range(len(percent)):
    try:
        percent = [float(i) for i in percent]
    except ZeroDivisionError:
        result = 0

print("graded assignments: ", len(score))

#calculation part
for i in range(len(score)):
    add = score[i]*percent[i]/100
    total = total + add
    denom = denom + percent[i]

total = total/denom*100
print(f"{total:05.2f}")

目前编写的PySide6代码

from PySide6 import QtCore, QtWidgets
from PySide6.QtWidgets import QMainWindow, QWidget, QLabel, QLineEdit,QApplication
from PySide6.QtWidgets import QPushButton
from PySide6.QtCore import QSize
raw_grade = []
indexes = []
index = 0
score = []
percent = []
fi_score = []
raw = []
add = 0
denom = 0
total = 0
import sys
import re
from operator import itemgetter


def multi_input(self):
    try:
        while True:
            self.nameLabel = QLabel(self)
            self.nameLabel.setText('Name:')
            self.line = QLineEdit(self)
            if not self.line.text(): break
            yield self.line.text()
    except KeyboardInterrupt:
        return

class MainWindow(QMainWindow):

    def __init__(self):

        QMainWindow.__init__(self)
        raw_grade = []
        indexes = []
        index = 0
        score = []
        percent = []
        fi_score = []
        raw = []
        add = 0
denom = 0
total = 0

        self.setMinimumSize(QSize(320, 140))
        self.setWindowTitle("PyQt Line Edit example (textfield) - pythonprogramminglanguage.com")

        multi_input(self)
        self.line = list(multi_input(self))


        pybutton = QPushButton('OK', self)
        pybutton.clicked.connect(self.clickMethod)
        pybutton.resize(200,32)
        pybutton.move(80, 60)

        for i in range(3, len(self.line), 4):
            index = i
            indexes.append(i)

        raw_grade = [self.line[id] for id in indexes]

        score = fi_score

        score = [value for value in score if value != ['']]

        for i in range(len(raw_grade)):
            gc = raw_grade[i].split('\t')
            raw.append(gc)

        for i in range(len(raw)):
            percent.append(raw[i][3])
            score.append(raw[i][4])

        for i in range(len(score)):
            use_score = score[i].split('/')
            fi_score.append(use_score)



        for i in range(len(score)):
            score[i] = [float(i) for i in score[i]]

        for i in range(len(score)):
            try:
                score[i] = score[i][0] / score[i][1] * 100
            except ZeroDivisionError:
                result = 0

        for i in range(len(percent)):
            try:
                percent[i] = percent[i].replace('%', '')
            except ZeroDivisionError:
                result = 0

        percent = [value for value in percent if value != '']

        for i in range(len(percent)):
            try:
                percent = [float(i) for i in percent]
            except ZeroDivisionError:
                result = 0

        print("graded assignments: ", len(score))

        # calculation part
        for i in range(len(score)):
            add = score[i] * percent[i] / 100
            total = total + add
            denom = denom + percent[i]

        self.line = total / denom * 100
        print('Your name: ' + self.line.text())
    def clickMethod(self):
        print('Your name: ' + self.line.text())

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()

问题原因及修复方案

核心问题

  1. 初始化阶段直接执行计算逻辑:在MainWindow的__init__里立刻执行所有计算代码,此时UI还没渲染完成,且没有等待用户输入,空数据直接引发错误导致闪退。
  2. UI逻辑错误:multi_input函数在循环里重复创建QLabel和QLineEdit,完全不符合用户输入的交互逻辑,而且直接把self.line覆盖为列表,后续调用.text()会报错。
  3. 变量作用域混乱:全局变量和类内局部变量重复定义,导致数据传递出错。

修复后的代码

from PySide6 import QtWidgets, QtCore
from PySide6.QtWidgets import (QMainWindow, QTextEdit, QPushButton, 
                               QVBoxLayout, QWidget, QLabel, QMessageBox)
import sys

class GradeCalculator(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("成绩计算器")
        self.setMinimumSize(600, 400)

        # 主部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        # 输入区域
        input_label = QLabel("粘贴从学校网站复制的成绩数据:")
        self.input_text = QTextEdit()
        self.input_text.setPlaceholderText("请粘贴多行成绩数据,格式与学校网站一致...")
        layout.addWidget(input_label)
        layout.addWidget(self.input_text)

        # 计算按钮
        calc_btn = QPushButton("计算总分")
        calc_btn.clicked.connect(self.calculate_total)
        layout.addWidget(calc_btn)

        # 结果显示区域
        self.result_label = QLabel("计算结果:")
        layout.addWidget(self.result_label)

    def calculate_total(self):
        # 获取输入数据
        input_data = self.input_text.toPlainText().splitlines()
        if not input_data:
            QMessageBox.warning(self, "警告", "请输入成绩数据!")
            return

        raw_grade = []
        indexes = []
        score = []
        percent = []
        fi_score = []
        raw = []
        add = 0.0
        denom = 0.0
        total = 0.0

        # 提取有效数据行(和原程序逻辑一致)
        for i in range(3, len(input_data), 4):
            indexes.append(i)
        raw_grade = [input_data[id] for id in indexes]

        # 解析成绩和占比
        for item in raw_grade:
            gc = item.split('\t')
            if len(gc) >=5:  # 确保数据格式正确
                raw.append(gc)
                percent.append(gc[3])
                score.append(gc[4])

        # 处理分数
        for s in score:
            use_score = s.split('/')
            if use_score != ['']:
                fi_score.append(use_score)

        # 转换为数值并计算百分比分数
        valid_scores = []
        for s in fi_score:
            try:
                if len(s) ==2:
                    score_num = float(s[0])/float(s[1])*100
                    valid_scores.append(score_num)
            except (ZeroDivisionError, ValueError):
                continue

        # 处理占比
        valid_percents = []
        for p in percent:
            p_clean = p.replace('%', '')
            if p_clean != '':
                try:
                    valid_percents.append(float(p_clean))
                except ValueError:
                    continue

        # 确保分数和占比数量匹配
        if len(valid_scores) != len(valid_percents):
            QMessageBox.warning(self, "错误", "数据格式异常,分数和占比数量不匹配!")
            return
        if not valid_scores:
            QMessageBox.warning(self, "错误", "未找到有效成绩数据!")
            return

        # 计算总分
        for s, p in zip(valid_scores, valid_percents):
            add += s * p / 100
            denom += p

        if denom ==0:
            QMessageBox.warning(self, "错误", "有效占比总和为0,无法计算总分!")
            return

        total = add / denom *100
        self.result_label.setText(f"计算结果:已评作业数量 {len(valid_scores)},总分 {total:05.2f}")

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = GradeCalculator()
    window.show()
    sys.exit(app.exec())

关键修改点

  • 使用QTextEdit替代单行输入框,适配原程序的多行粘贴输入需求。
  • 将所有计算逻辑移到按钮点击的槽函数calculate_total中,确保用户输入完成后再触发计算。
  • 添加了数据校验和错误提示,避免空输入、格式错误导致的崩溃。
  • 整理了变量作用域,全部使用类内局部变量,避免全局变量干扰。
  • 优化了UI布局,使用垂直布局让界面更合理,操作更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:20:30