我有一个类似下面的代码,可以使用 PyQt5 库将 HTML 打印为 PDF。通过 VS code 函数核心工具测试时,此代码工作正常,但是当将其部署为 azure 函数应用程序时,我收到错误 - QT 平台插件无法初始化。重新安装应用程序可能会修复。
当我设置
os.environ["QT_QPA_PLATFORM"] = "offscreen"
时,我收到一个不同的错误:WebEngineContext used before QTWebEngine::Initialize()
有没有办法使用 PyQt5 将其作为函数应用程序在 Azure 应用服务环境上运行?
import logging
import azure.functions as func
import os
import sys
import tempfile
from PyQt5 import QtWidgets, QtWebEngineWidgets, QtCore
from PyQt5.QtGui import QPageLayout, QPageSize
# Set the environment variable for Qt
class PDFGenerator:
def __init__(self, url):
self.url = url
self.app = QtWidgets.QApplication(sys.argv)
self.loader = QtWebEngineWidgets.QWebEngineView()
# os.environ["QT_QPA_PLATFORM"] = "offscreen"
self.loader.setZoomFactor(1)
self.layout = QPageLayout()
self.layout.setPageSize(QPageSize(QPageSize.A4Extra))
self.layout.setOrientation(QPageLayout.Portrait)
self.loader.page().pdfPrintingFinished.connect(self.on_pdf_printed)
self.loader.loadFinished.connect(self.emit_pdf)
self.load_url()
def load_url(self):
self.loader.load(QtCore.QUrl(self.url))
def emit_pdf(self):
output_path = os.path.join(tempfile.gettempdir(), 'output.pdf')
self.loader.page().printToPdf(output_path, self.layout)
def on_pdf_printed(self, path, success):
if success:
logging.info(f"PDF saved to {path}")
else:
logging.error("Failed to save PDF")
self.app.quit()
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
try:
# Hardcoded URL
url = "https://www.example.com"
pdf_generator = PDFGenerator(url)
pdf_generator.app.exec_()
except Exception as e:
logging.error(f"Error: {e}")
return func.HttpResponse(f"Error: {e}", status_code=500)
return func.HttpResponse(f"PDF generation completed for {url}", status_code=200)
将函数应用部署到azure,但由于QT初始化失败而无法执行。
感谢musicamante的评论。事实上,如果您想在 Function App 中执行代码,您可以使用 QWebEnginePage。
我修改了您的代码,其中我使用QWebEnginePage。
import azure.functions as func
import logging
import os
import sys
import tempfile
from PyQt5.QtCore import QUrl, QEventLoop
from PyQt5.QtWebEngineWidgets import QWebEnginePage
from PyQt5.QtGui import QPageLayout, QPageSize
from PyQt5.QtWidgets import QApplication
os.environ['QT_QPA_PLATFORM'] = 'offscreen'
os.environ['QTWEBENGINE_CHROMIUM_FLAGS'] = '--no-sandbox'
class PDFGenerator(QWebEnginePage):
def __init__(self, url):
super().__init__()
self.url = url
self.output_path = os.path.join(tempfile.gettempdir(), "output.pdf")
self.layout = QPageLayout()
self.layout.setPageSize(QPageSize(QPageSize.A4Extra))
self.layout.setOrientation(QPageLayout.Portrait)
self.loop = QEventLoop()
self.loadFinished.connect(self.on_load_finished)
logging.info(f"Loading URL: {self.url}")
self.load(QUrl(self.url))
def on_load_finished(self, success):
if success:
logging.info(f"Page loaded successfully: {self.url}")
logging.info("Starting PDF generation...")
try:
self.printToPdf(self.on_pdf_generated, self.layout)
except Exception as e:
logging.error(f"Error during PDF generation: {e}", exc_info=True)
self.loop.quit()
else:
logging.error(f"Failed to load the page: {self.url}")
self.loop.quit()
def on_pdf_generated(self, pdf_content):
try:
with open(self.output_path, "wb") as f:
f.write(pdf_content)
logging.info(f"PDF successfully saved to: {self.output_path}")
except Exception as e:
logging.error(f"Error saving PDF: {e}", exc_info=True)
finally:
self.loop.quit()
def generate(self):
self.loop.exec_()
return self.output_path
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
@app.route(route="http_trigger")
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
try:
url = "https://www.wikipedia.org/"
logging.info(f"Initializing PDF generation for URL: {url}")
app = QApplication(sys.argv)
pdf_generator = PDFGenerator(url)
pdf_path = pdf_generator.generate()
return func.HttpResponse(
f"PDF successfully generated and saved at {pdf_path}",
status_code=200
)
except Exception as e:
logging.error(f"Error: {e}", exc_info=True)
return func.HttpResponse(f"Error: {e}", status_code=500)
我的requirements.txt 文件中有以下模块。
azure-functions
PyQt5
qtgui
PyQtWebEngine
我已将此代码部署在应用程序服务计划中的 Function App 中,并且还在环境变量中添加了
QT_QPA_PLATFORM
和 QTWEBENGINE_CHROMIUM_FLAGS
。