在 QtPy5 中如何将 CookieStore 刷新到磁盘?

How do you flush the CookieStore to disk in QtPy5?

我的目标是将 QWebEngineView cookie 保存到磁盘,以便在打开该小部件的应用程序关闭时,cookie 始终在应用程序退出之前可靠地保存到磁盘。这样,当再次执行该应用程序时,它将以先前 运行 的 cookie 值开始。

使用下面的代码,将新的 cookie 值实际写入磁盘几乎需要整整一分钟。如果应用程序在此之前关闭,新的 cookie 值将 永远不会 写入磁盘。

这是一个示例程序,它使用 PyQt5 和 QWebEngineView 将 cookie 保存到磁盘:Python3 在 Windows 10 中打开网页:

from pathlib import Path
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineProfile
import sys

site = 'https://whosebug.com/search?q=pyqt5+forcepersistentcookies'


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        QMainWindow.__init__(self, *args, **kwargs)
        self.webview = QWebEngineView()

        profile = QWebEngineProfile.defaultProfile()
        profile.setPersistentCookiesPolicy(QWebEngineProfile.ForcePersistentCookies)
        browser_storage_folder = Path.home().as_posix() + '/.test_cookies'
        profile.setPersistentStoragePath(browser_storage_folder)

        webpage = QWebEnginePage(profile, self.webview)
        self.webview.setPage(webpage)
        self.webview.load(QUrl(site))
        self.setCentralWidget(self.webview)

    def closeEvent(self, event):
        print('Close Event')
        profile = QWebEngineProfile.defaultProfile()
        profile.deleteLater()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

虽然上面的代码有效——如果你查看 Cookies 文件,你会看到它在页面加载后得到更新——页面加载后需要将近 整分钟在文件中更新 cookie 之前加载:

C:\Users\<My User Account>\.test_cookies\Cookies

如果 window 在此之前关闭,更新的 cookie 将丢失。当 PyQt5 应用程序关闭时,如何强制 cookiestore 刷新到磁盘?我能找到的所有提示是 at doc.qt.io 上面写着:

A disk-based QWebEngineProfile should be destroyed on or before application exit, otherwise the cache and persistent data may not be fully flushed to disk.

没有提示如何在 Python 中销毁 QWebEngineProfile。在变量上调用 del 不会执行任何操作。在配置文件上调用 deleteLater 也不会执行任何操作。更改代码以创建全新的配置文件 self.profile = QWebEngineProfile("storage", self.webview),在任何地方使用它,然后在 closeEvent 中调用 self.profile.deleteLater() 没有任何作用。

我从 Florian Bruhin 那里得到了 mailing list 的答复。他的消息指出,我 运行 遇到的问题已在 PyQt 5.13 中以可选的新退出方案解决,并在 PyQt 5.14 及更高版本中默认解决。

旧版本有一个解决方法,我已经测试过并且效果很好。解决方法是从 cookiestore 中删除一个 non-existent cookie,这会导致 cookiestore 立即刷新到磁盘:

cookie = QNetworkCookie()
QWebEngineProfile.defaultProfile().cookieStore().deleteCookie(cookie)