恢复乳胶编译错误 [英] Recovering Latex Compilation Errors

查看:91
本文介绍了恢复乳胶编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个编写文本的程序,当我单击编译按钮时,它会编译为乳胶,转换为pdf并显示在我的应用程序中。
问题是,当我遇到编译错误时,应用程序就会出错,仅此而已。
我想知道是否有可能在不使应用程序崩溃的情况下恢复编译错误。
我尝试了try / expect,但这不是python错误,因此无法正常工作。



您将需要PDF.js来查看pdf



注意:试试-除外仅处理python代码引发的异常(不是错误),而不处理其他程序(例如作为pdflatex。对于QProcess,readyReadStandardOutput和readyReadStandardError信号分别通知程序中是否有stdout和stderr信息(在本例中为pdflatex),可以分别使用readAllStandardOutput()和readAllStandardError()方法进行检索。该信息将打印在控制台上


I have a program to write a text and when I click on the 'compile' button, it compiles to latex, converts to pdf and displays it on my application. The problem is that when I have a compilation error, the application bugs and that's it. I'd like to know if it's possible to recover compilation errors without the application crashing. I tried with try/expect but it's not a python error so it doesn't work.

You will need PDF.js to view the pdf https://mozilla.github.io/pdf.js/getting_started/#download

Ui :

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(841, 481)
        self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.textEdit = QtWidgets.QTextEdit(Dialog)
        self.textEdit.setMinimumSize(QtCore.QSize(0, 200))
        self.textEdit.setObjectName("textEdit")
        self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)
        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
        self.buttonBox.setOrientation(QtCore.Qt.Vertical)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.gridLayout.addWidget(self.buttonBox, 0, 1, 1, 1)
        #self.textEdit_2 = QtWidgets.QTextEdit(Dialog)
        #self.textEdit_2.setObjectName("textEdit_2")
        #self.gridLayout.addWidget(self.textEdit_2, 1, 0, 1, 1)
        self.horizontalLayout.addLayout(self.gridLayout)

        self.retranslateUi(Dialog)
        self.buttonBox.accepted.connect(Dialog.accept)
        self.buttonBox.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

app:

import os
import sys
from PyQt5.QtWidgets import QDialog, QPushButton, QWidget, QApplication
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
from sympy import Symbol
import untitled

x=Symbol('x')
class Test(QDialog, untitled.Ui_Dialog):
    def __init__(self):
        super(Test, self).__init__()
        self.setupUi(self)

        self.bouton= QPushButton('compile',self)
        self.horizontalLayout.addWidget(self.bouton)
        self.bouton.clicked.connect(self.crertest)

        self.widget = QWidget(self)
        self.gridLayout.addWidget(self.widget, 1, 0, 1, 1)
        self.t = Window()
        lay = QtWidgets.QVBoxLayout(self.widget)
        lay.addWidget(self.t)

    def crertest(self):
        try :
            def preambule(*packages):
                p = ""
                for i in packages:
                    p = p + "\\usepackage{" + i + "}\n"
                return p
            start = "\\documentclass[12pt,a4paper,french]{article}\n\\usepackage[utf8]{inputenc}\n"
            start = start + preambule('amsmath','graphicx')
            start = start + "\\begin{document}\n"
            end = "\\end{document}"
            body = self.textEdit.toPlainText()

            container = start + body + end
            file = "mypdf.tex"
            if os.path.exists(file):
                os.remove(file)
            fichier = open("mypdf.tex", "x")  #
            fichier.write(container)
            fichier.close()

            instructions = "pdflatex " + file
            os.system(instructions)
            readpdf = "START " + file[:-4] + ".pdf"
            self.t.loadd()
        except:
            print('Fail')

PDFJS = 'file:///C:/Users/pdf_js/web/viewer.html' #Path too viewer.htlm in your pddf_js folder
PDF = 'file:///C:/Users/mypdf.pdf' #Path to your pdf


class Window(QtWebEngineWidgets.QWebEngineView):
    def __init__(self):
        super(Window, self).__init__()
        self.loadd()
    try:
        def loadd(self):
            self.load(QtCore.QUrl.fromUserInput('%s?file=%s' % (PDFJS, PDF)))
    except:
        print ('Fail 2')
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Test()
    main.show()
    app.exec_()

I use the code taken from this post for the pdf display : How to render PDF using pdf.js viewer in PyQt?

Exactly like a latex editor like Texmaker does.

Edit.

I put the part of the program that compiles in latex and displays the pdf in another module.

I call the module on my main file, except that I have to compile the program twice to get an update of the display. Sometimes it's after compiling 3/4 times that the bug appeared. I need to add something to run it once ?

compile : test.py

import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets


CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
TMP_DIR = os.path.join(CURRENT_DIR, "tmp")
PDFJS = os.path.join(CURRENT_DIR, "3rdParty/pdfjs-2.2.228-dist/web/viewer.html")


def create_document(content, packages):
    lines = (
        r"\documentclass[12pt,a4paper,french]{article}",
        r"\usepackage[utf8]{inputenc}",
        *(r"\usepackage {%s}" % (package,) for package in packages),
        r"\begin{document}",
        content,
        r"\end{document}",
    )
    return "\n".join(lines)


class PdfViewer(QtWebEngineWidgets.QWebEngineView):
    def load_pdf(self, filename):
        url = QtCore.QUrl.fromUserInput(
            "%s?file=%s" % (QtCore.QUrl.fromLocalFile(PDFJS).toString(), filename)
        )
        self.load(url)


class Compile:
    def __init__(self, parent):
        super().__init__()
        self.process = QtCore.QProcess(parent)
        self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
        self.process.finished.connect(self.on_finished)
        self.process.setProgram("pdflatex")

        self.basename = "mypdf"

    def compile(self,body):
        doc = create_document(body, ("amsmath", "graphicx"))
        QtCore.QDir().mkpath(TMP_DIR)
        self.qfile = QtCore.QFile(os.path.join(TMP_DIR, self.basename + ".tex"))
        if self.qfile.open(QtCore.QIODevice.WriteOnly):
            self.qfile.write(doc.encode())
            self.qfile.close()

        self.process.setArguments(
            [
                "-interaction=nonstopmode",
                "-jobname={}".format(self.basename),
                "-output-directory={}".format(TMP_DIR),
                self.qfile.fileName(),
            ]
        )
        self.process.start()

    def on_readyReadStandardOutput(self):
        print(self.process.readAllStandardOutput().data().decode(), end='')

    def on_finished(self):
        self.qfile.remove()

call with :

import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
import test


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.input = QtWidgets.QTextEdit()
        self.input.setText('.')

        self.a = test.Compile(self)
        self.a.compile('.')
        self.b = test.PdfViewer()
        self.b.load_pdf(your PDF path)

        compile_button = QtWidgets.QPushButton(self.tr("Compile"))

        lay = QtWidgets.QGridLayout(self)
        lay.addWidget(compile_button, 0, 0, 1, 2)
        lay.addWidget(self.input, 1, 0)
        lay.addWidget(self.b, 1, 1)
        lay.setColumnStretch(0, 1)
        lay.setColumnStretch(1, 1)

        compile_button.clicked.connect(self.call)

    def call(self):
        self.a.compile(self.input.toPlainText())
        self.b.load_pdf(your PDF path)


def main():
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.showMaximized()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

解决方案

It is difficult to know the error of your problem since there can be many causes so I have created my example from scratch. To do this you must have the following file structure: At the side of the script there must be a folder called 3rdParty where you must unzip the file downloaded from PDF.js.

├── 3rdParty
│   └── pdfjs-2.2.228-dist
│       ├── build
│       │   ├── pdf.js
│       │   ├── pdf.js.map
│       │   ├── pdf.worker.js
│       │   └── pdf.worker.js.map
│       ├── LICENSE
│       └── web
│           ├── cmaps
│           ├── compressed.tracemonkey-pldi-09.pdf
│           ├── debugger.js
│           ├── images
│           ├── locale
│           ├── viewer.css
│           ├── viewer.html
│           ├── viewer.js
│           └── viewer.js.map
├── main.py
└── tmp

Instead of using os.system () it is better to use a method that gives feedback on the state of the conversion, in this case use QProcess, in addition to adding more options such as "-interaction=nonstopmode", "-jobname=FILENAME" and "-output-directory=DIR" that allow that there is no interactive mode, point to the folder Output and name of pdf:

import os
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
TMP_DIR = os.path.join(CURRENT_DIR, "tmp")
PDFJS = os.path.join(CURRENT_DIR, "3rdParty/pdfjs-2.2.228-dist/web/viewer.html")


def create_document(content, packages):
    lines = (
        r"\documentclass[12pt,a4paper,french]{article}",
        r"\usepackage[utf8]{inputenc}",
        *(r"\usepackage {%s}" % (package,) for package in packages),
        r"\begin{document}",
        content,
        r"\end{document}",
    )
    return "\n".join(lines)


class PdfViewer(QtWebEngineWidgets.QWebEngineView):
    def load_pdf(self, filename):
        url = QtCore.QUrl.fromUserInput(
            "%s?file=%s" % (QtCore.QUrl.fromLocalFile(PDFJS).toString(), filename)
        )
        self.load(url)


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.input = QtWidgets.QTextEdit()
        self.output = PdfViewer()

        compile_button = QtWidgets.QPushButton(self.tr("Compile"))

        lay = QtWidgets.QGridLayout(self)
        lay.addWidget(compile_button, 0, 0, 1, 2)
        lay.addWidget(self.input, 1, 0)
        lay.addWidget(self.output, 1, 1)
        lay.setColumnStretch(0, 1)
        lay.setColumnStretch(1, 1)

        compile_button.clicked.connect(self.compile)

        self.process = QtCore.QProcess(self)
        self.process.readyReadStandardError.connect(self.on_readyReadStandardError)
        self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
        self.process.finished.connect(self.on_finished)
        self.process.setProgram("pdflatex")

        self.basename = "mypdf"

    def compile(self):
        doc = create_document(self.input.toPlainText(), ("amsmath", "graphicx"))
        QtCore.QDir().mkpath(TMP_DIR)
        self.qfile = QtCore.QFile(os.path.join(TMP_DIR, self.basename + ".tex"))
        if self.qfile.open(QtCore.QIODevice.WriteOnly):
            self.qfile.write(doc.encode())
            self.qfile.close()

        self.process.setArguments(
            [
                "-interaction=nonstopmode",
                "-jobname={}".format(self.basename),
                "-output-directory={}".format(TMP_DIR),
                self.qfile.fileName(),
            ]
        )
        self.process.start()

    def on_readyReadStandardError(self):
        print(self.process.readAllStandardError().data().decode(), end='')

    def on_readyReadStandardOutput(self):
        print(self.process.readAllStandardOutput().data().decode(), end='')

    def on_finished(self):
        self.qfile.remove()
        pdf_filename = os.path.join(TMP_DIR, self.basename + ".pdf")
        self.output.load_pdf(pdf_filename)


def main():
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.showMaximized()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

Note: try-except only handles the exceptions (not errors) thrown by the python code, not by other programs such as pdflatex. In the case of QProcess the readyReadStandardOutput and readyReadStandardError signal notifies if there is stdout and stderr information from the program(in this case pdflatex), respectively and can be retrieved using the readAllStandardOutput() and readAllStandardError() methods, respectively. That information is printed on the console

这篇关于恢复乳胶编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆