How do you flush the CookieStore to disk in QtPy5?

701 Views Asked by At

My goal is to have QWebEngineView cookies saved to disk so that if the application opening that widget is closed, the cookies are reliably saved to disk before the application exits, always. That way, when the application is executed again, it will start out with the previous run's cookie values.

Using the code below, it takes almost a full minute for new cookie values to actually be written to disk. If the application is closed before that point, the new cookie values are never written to disk at all.

Here is an example program that opens a web page in Python3 in Windows 10 using PyQt5 and a QWebEngineView with cookies saved to disk:

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://stackoverflow.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_())

While the code above works -- if you watch the Cookies file you'll see it get updated after the page loads -- it takes nearly a full minute after the page loads before the cookies are updated in the file:

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

If the window is closed before this happens, the updated cookies are lost. How do you force the cookiestore to flush to disk when a PyQt5 application closes? All I can find as a hint is at doc.qt.io where it says:

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.

There is no hint how to destroy a QWebEngineProfile in Python. Calling del on the variable doesn't do anything. Calling deleteLater on the profile also doesn't do anything. Changing the code to make a brand new profile self.profile = QWebEngineProfile("storage", self.webview), using that everywhere, and then in closeEvent calling self.profile.deleteLater() doesn't do anything.

1

There are 1 best solutions below

1
On BEST ANSWER

I got an answer on the mailing list from Florian Bruhin. His message pointed out that the issue I'm running into is addressed in PyQt 5.13 in an optional new exit scheme and addressed by default in PyQt 5.14 and later.

A workaround exists for older versions, which I have tested and it works well. The workaround is to delete a non-existent cookie from the cookiestore, which causes the cookiestore to be flushed to disk right away:

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