解释:
正如the docs 指出的那样:
您需要注意本地测试 — 如果您尝试在本地加载 HTML 文件(即使用 file:// URL),由于 JavaScript 模块的安全要求,您会遇到 CORS 错误。您需要通过服务器进行测试。
如果您使用本地文件,则无法访问这些模块,因此您会收到错误消息:
js: Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.
解决方案:
在这种情况下,有 2 个选项:
1。本地服务器
实现一个服务器,例如使用aiohttp + qasync:
import asyncio
import functools
import os
from pathlib import Path
import sys
from aiohttp import web
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWebEngineWidgets import QWebEngineView
import qasync
from qasync import QApplication
application_path = (
Path(sys.executable).resolve().parent
if getattr(sys, "frozen", False)
else Path(__file__).resolve().parent
)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.browser = QWebEngineView()
config_name = "/data_files/init.html"
url = QUrl("http://localhost:4000")
url.setPath(config_name)
self.browser.load(url)
self.setCentralWidget(self.browser)
self.showMaximized()
async def main():
def close_future(future, loop):
loop.call_later(10, future.cancel)
future.cancel()
loop = asyncio.get_event_loop()
future = asyncio.Future()
qt_app = QApplication.instance()
if hasattr(qt_app, "aboutToQuit"):
getattr(qt_app, "aboutToQuit").connect(
functools.partial(close_future, future, loop)
)
app = web.Application()
app.router.add_static("/", application_path, show_index=True)
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, "localhost", 4000)
await site.start()
view = MainWindow()
view.show()
await future
await runner.cleanup()
return True
if __name__ == "__main__":
try:
qasync.run(main())
except asyncio.exceptions.CancelledError:
sys.exit(0)
2。自定义 QWebEngineUrlSchemeHandler
import sys
import os
from PyQt5.QtCore import QCoreApplication, QUrl, QFile, QFileInfo, QMimeDatabase
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineCore import (
QWebEngineUrlScheme,
QWebEngineUrlSchemeHandler,
QWebEngineUrlRequestJob,
)
from PyQt5.QtWebEngineWidgets import QWebEngineView
application_path = (
os.path.dirname(sys.executable)
if getattr(sys, "frozen", False)
else os.path.dirname(__file__)
)
class QtSchemeHandler(QWebEngineUrlSchemeHandler):
def requestStarted(self, job):
request_method = job.requestMethod()
if request_method != b"GET":
job.fail(QWebEngineUrlRequestJob.RequestDenied)
return
request_url = job.requestUrl()
request_path = request_url.path()
file = QFile(application_path + request_path)
file.setParent(job)
job.destroyed.connect(file.deleteLater)
if not file.exists() or file.size() == 0:
print(f"resource '{request_path}' not found or is empty")
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
return
file_info = QFileInfo(file)
mime_database = QMimeDatabase()
mime_type = mime_database.mimeTypeForFile(file_info)
job.reply(mime_type.name().encode(), file)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.browser = QWebEngineView()
self.scheme_handler = QtSchemeHandler()
self.browser.page().profile().installUrlSchemeHandler(
b"qt", self.scheme_handler
)
filename = "/data_files/init.html"
url = QUrl("qt://main")
url.setPath(filename)
self.browser.load(url)
self.setCentralWidget(self.browser)
if __name__ == "__main__":
scheme = QWebEngineUrlScheme(b"qt")
scheme.setFlags(QWebEngineUrlScheme.CorsEnabled)
QWebEngineUrlScheme.registerScheme(scheme)
app = QApplication(sys.argv)
QApplication.setApplicationName("v0.1")
window = MainWindow()
window.show()
app.exec_()
文件结构:
├── data_files
│ ├── init.html
│ └── js
│ └── main.js
└── main.py