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

Python中PyQt5与PyPDF2合并PDF时函数连接崩溃问题求助

问题分析与解决建议

嘿,我一眼就看出几个导致程序崩溃的关键问题,咱们一步步来解决:

核心问题

  1. 槽函数参数不匹配:Qt的QPushButton.clicked信号默认会传递一个布尔值(表示按钮是否被按下),但你的laczeniePdf函数定义了需要两个参数g和h。当点击Start按钮时,信号只传一个参数,函数却要两个,直接触发参数错误导致崩溃。
  2. 未保存选中的文件信息:你的openFile1和openFile2函数虽然返回了文件对象,但Qt的槽函数返回值会被完全忽略,这些文件对象根本没被保存下来,就算参数问题解决了,laczeniePdf也拿不到之前选中的文件。
  3. 文件对象生命周期问题:就算你能拿到返回的文件对象,Python的垃圾回收机制可能会在你调用laczeniePdf前就把它关闭,导致读取PDF失败。

修复方案

咱们调整代码,用类的实例变量保存选中的文件路径(比保存文件对象更安全),修正槽函数参数,同时添加异常处理避免崩溃:

修改后的完整代码

import sys
from PyQt5 import QtWidgets, QtCore
import PyPDF2

class Ui_PolaczPliki(object):
    def setupUi(self, PolaczPliki):
        PolaczPliki.setObjectName("PolaczPliki")
        PolaczPliki.resize(295, 113)
        
        # 初始化实例变量,保存选中的文件路径
        self.file_path1 = None
        self.file_path2 = None
        
        self.btnPlik1 = QtWidgets.QPushButton(PolaczPliki)
        self.btnPlik1.setGeometry(QtCore.QRect(30, 40, 91, 41))
        self.btnPlik1.setObjectName("btnPlik1")
        self.btnPlik1.clicked.connect(self.openFile1)
        
        self.btnPlik2 = QtWidgets.QPushButton(PolaczPliki)
        self.btnPlik2.setGeometry(QtCore.QRect(160, 40, 91, 41))
        self.btnPlik2.setObjectName("btnPlik2")
        self.btnPlik2.clicked.connect(self.openFile2)
        
        self.btnPlik3 = QtWidgets.QPushButton(PolaczPliki)
        self.btnPlik3.setGeometry(QtCore.QRect(80, 80, 40, 20))
        self.btnPlik3.setObjectName("btnPlik3")
        self.btnPlik3.clicked.connect(self.laczeniePdf)
        
        self.label = QtWidgets.QLabel(PolaczPliki)
        self.label.setGeometry(QtCore.QRect(50, 10, 47, 13))
        self.label.setObjectName("label")
        
        self.label_2 = QtWidgets.QLabel(PolaczPliki)
        self.label_2.setGeometry(QtCore.QRect(180, 10, 47, 13))
        self.label_2.setObjectName("label_2")
        
        self.retranslateUi(PolaczPliki)
        QtCore.QMetaObject.connectSlotsByName(PolaczPliki)

    def retranslateUi(self, PolaczPliki):
        _translate = QtCore.QCoreApplication.translate
        PolaczPliki.setWindowTitle(_translate("PolaczPliki", "Polacz pliki"))
        self.btnPlik1.setText(_translate("PolaczPliki", "Dodaj"))
        self.btnPlik2.setText(_translate("PolaczPliki", "Dodaj"))
        self.btnPlik3.setText(_translate("PolaczPliki", "Start"))
        self.label.setText(_translate("PolaczPliki", "Plik nr 1"))
        self.label_2.setText(_translate("PolaczPliki", "Plik nr 2"))

    def openFile1(self):
        pathFileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Wybierz plik', '', 'pdf(*.pdf)')
        print("PathFileName-'{}', \n_-'{}'".format(pathFileName, _))
        if pathFileName:
            print("Wybrany plik: ", pathFileName)
            # 保存文件路径到实例变量,而不是返回文件对象
            self.file_path1 = pathFileName

    def openFile2(self):
        pathFileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Wybierz plik', '', 'pdf(*.pdf)')
        print("PathFileName-'{}', \n_-'{}'".format(pathFileName, _))
        if pathFileName:
            print("Wybrany plik: ", pathFileName)
            # 保存文件路径到实例变量
            self.file_path2 = pathFileName

    def laczeniePdf(self):
        # 先检查是否选中了两个文件
        if not self.file_path1 or not self.file_path2:
            QtWidgets.QMessageBox.warning(None, "Błąd", "Proszę wybrać oba pliki PDF!")
            return
        
        try:
            # 使用with语句自动管理文件,无需手动close
            with open(self.file_path1, 'rb') as f1, open(self.file_path2, 'rb') as f2, open('FinalOutput.pdf', 'wb') as output_file:
                reader1 = PyPDF2.PdfFileReader(f1)
                reader2 = PyPDF2.PdfFileReader(f2)
                writer = PyPDF2.PdfFileWriter()
                
                # 添加所有页面
                for page in range(reader1.getNumPages()):
                    writer.addPage(reader1.getPage(page))
                for page in range(reader2.getNumPages()):
                    writer.addPage(reader2.getPage(page))
                
                writer.write(output_file)
            
            QtWidgets.QMessageBox.information(None, "Sukces", "Pliki zostały połączone pomyślnie!")
        except Exception as e:
            QtWidgets.QMessageBox.critical(None, "Błąd", f"Wystąpił błąd podczas łączenia: {str(e)}")

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    # 修正实例化错误,匹配当前类
    ex = Ui_PolaczPliki()
    w = QtWidgets.QMainWindow()
    ex.setupUi(w)
    w.show()
    sys.exit(app.exec_())

关键修改点

  • 添加了self.file_path1和self.file_path2实例变量,用来保存用户选中的PDF路径,替代原来的返回值方式。
  • 修改laczeniePdf函数,去掉了多余的参数,直接从实例变量获取文件路径,符合Qt槽函数的调用规则。
  • 使用with语句管理文件,自动关闭文件句柄,避免资源泄漏。
  • 添加了异常处理和用户提示:如果没选文件就点Start,会弹出警告;合并过程中出错会显示具体错误信息;成功后也会提示用户。
  • 修正了主程序中的实例化错误(原来的Ui_MainWindow改成了Ui_PolaczPliki,否则窗口不会正确显示)。

额外提示

如果你用的是较新版本的PyPDF2,PdfFileReader和PdfFileWriter已经被标记为过时,推荐使用PdfReader和PdfWriter,用法基本一致,只需要替换类名即可:

reader1 = PyPDF2.PdfReader(f1)
reader2 = PyPDF2.PdfReader(f2)
writer = PyPDF2.PdfWriter()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:08:47