【问题标题】:How to use PyQT5 to convert multiple HTML docs to PDF in one loop如何使用 PyQT5 将多个 HTML 文档一次循环转换为 PDF
【发布时间】:2020-02-14 21:33:27
【问题描述】:

我正在编写一个程序,该程序使用从 PDF 转换为 HTML 的通用模板来为个人创建个性化报告。为了将最终的 HTML 文件转换回 PDF,我使用了 PyQT5 及其 printToPdf 方法。它曾经完美地工作过,但程序挂起,直到我关闭打开的小部件视图,此时它会出现段错误并结束整个 python 程序。如何以编程方式和平地关闭程序,以便我可以一次性渲染所有 HTML?也许有什么方法可以不让线程放弃到小部件?

这是我当前的代码。

for htmlFileAsString in files:

   app = QtWidgets.QApplication(sys.argv)
   loader = QtWebEngineWidgets.QWebEngineView()
   loader.setZoomFactor(1)
   loader.setHtml(htmlFileAsString)
   loader.page().pdfPrintingFinished.connect(
     lambda *args: print('finished:', args))
   def emit_pdf(finished):
     loader.show()
     loader.page().printToPdf('output/' + name + '/1.pdf')

   loader.loadFinished.connect(emit_pdf)
   app.exec()

【问题讨论】:

  • loop在哪里?
  • 我提供的代码 sn-p 应该是循环的主体,每个循环都将一个新的 html 文件转换为 pdf。我将进行编辑以澄清。

标签: python html pdf pyqt pyqt5


【解决方案1】:

我在堆栈溢出方面没有足够的声誉来发表评论,所以我发布了回复。

@eyllanesc 发布的代码需要编辑一下才能工作:

import os
from PyQt5 import QtWidgets, QtWebEngineWidgets


class PdfPage(QtWebEngineWidgets.QWebEnginePage):
    def __init__(self):
        super().__init__()
        self._htmls_and_paths = []
        self._current_path = ""

        self.setZoomFactor(1)
        self.loadFinished.connect(self._handleLoadFinished)
        self.pdfPrintingFinished.connect(self._handlePrintingFinished)

    def convert(self, htmls, paths):
        self._htmls_and_paths = iter(zip(htmls, paths))
        self._fetchNext()

    def _fetchNext(self):
        try:
            self._current_html, self._current_path = next(self._htmls_and_paths)
        except StopIteration:
            return False
        else:
            self.setHtml(self._current_html)
        return True

    def _handleLoadFinished(self, ok):
        if ok:
            self.printToPdf(self._current_path)

    def _handlePrintingFinished(self, filePath, success):
        print("finished:", filePath, success)
        if not self._fetchNext():
            QtWidgets.QApplication.quit()


if __name__ == "__main__":

    current_dir = os.path.dirname(os.path.realpath(__file__))

    paths = []
    htmls = []
    for i in range(10):
        html = """<html>
    <header><title>This is title</title></header>
    <body>
    Hello world-{i}
    </body>
    </html>""".format(
            i=i
        )
        htmls.append(html)
        paths.append(os.path.join(current_dir, "{}.pdf".format(i)))

    app = QtWidgets.QApplication([])
    page = PdfPage()
    page.convert(htmls, paths)
    app.exec_()

    print("finished")

具体来说,setHtmlprintToPdf 的输入需要更改。

【讨论】:

    【解决方案2】:

    the ekhumoro answer 中所述,问题在于您无法创建多个 QApplication(您必须查看所指示的答案以了解更多详细信息),因此应用相同的技术,解决方案如下:

    import os
    from PyQt5 import QtWidgets, QtWebEngineWidgets
    
    
    class PdfPage(QtWebEngineWidgets.QWebEnginePage):
        def __init__(self):
            super().__init__()
            self._htmls_and_paths = []
            self._current_path = ""
    
            self.setZoomFactor(1)
            self.loadFinished.connect(self._handleLoadFinished)
            self.pdfPrintingFinished.connect(self._handlePrintingFinished)
    
        def convert(self, htmls, paths):
            self._htmls_and_paths = iter(zip(htmls, paths))
            self._fetchNext()
    
        def _fetchNext(self):
            try:
                self._current_path, path = next(self._htmls_and_paths)
            except StopIteration:
                return False
            else:
                self.setHtml(html)
            return True
    
        def _handleLoadFinished(self, ok):
            if ok:
                self.printToPdf(self._current_path)
    
        def _handlePrintingFinished(self, filePath, success):
            print("finished:", filePath, success)
            if not self._fetchNext():
                QtWidgets.QApplication.quit()
    
    
    if __name__ == "__main__":
    
        current_dir = os.path.dirname(os.path.realpath(__file__))
    
        paths = []
        htmls = []
        for i in range(10):
            html = """<html>
        <header><title>This is title</title></header>
        <body>
        Hello world-{i}
        </body>
        </html>""".format(
                i=i
            )
            htmls.append(html)
            paths.append(os.path.join(current_dir, "{}.pdf".format(i)))
    
        app = QtWidgets.QApplication([])
        page = PdfPage()
        page.convert(htmls, paths)
        app.exec_()
    
        print("finished")
    

    【讨论】:

    • 谢谢。通过细微的更改,这主要是有效的。您知道是否有任何方法在应用程序完成时不发出段错误?如果可能,我想继续使用原始 python 脚本。此外,一些 pdf(全部来自同一个模板)只显示背景图片(没有文字),我不知道为什么。
    • TJohn2017 我遇到了同样的问题。我使用pyqt5生成pdf后脚本崩溃了,你解决了这个问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多