How to close PyQt QtApplication correctly?

I don't know the first thing about Qt, but I'm trying to be sassy and borrow code from other sources (http://lateral.netmanagers.com.ar/weblog/posts/BB901.html#disqus_thread);)

I have a problem. When I run test () for the first time, everything runs smoothly. However, when I run it a second time, I get nasty segfaults. I suspect the problem is that I am not finishing qt. What should I change about this program so that it works several times? Thanks in advance!

from PyQt4 import QtCore, QtGui, QtWebKit import logging logging.basicConfig(level=logging.DEBUG) class Capturer(object): """A class to capture webpages as images""" def __init__(self, url, filename, app): self.url = url self.app = app self.filename = filename self.saw_initial_layout = False self.saw_document_complete = False def loadFinishedSlot(self): self.saw_document_complete = True if self.saw_initial_layout and self.saw_document_complete: self.doCapture() def initialLayoutSlot(self): self.saw_initial_layout = True if self.saw_initial_layout and self.saw_document_complete: self.doCapture() def capture(self): """Captures url as an image to the file specified""" self.wb = QtWebKit.QWebPage() self.wb.mainFrame().setScrollBarPolicy( QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) self.wb.mainFrame().setScrollBarPolicy( QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff) self.wb.loadFinished.connect(self.loadFinishedSlot) self.wb.mainFrame().initialLayoutCompleted.connect( self.initialLayoutSlot) logging.debug("Load %s", self.url) self.wb.mainFrame().load(QtCore.QUrl(self.url)) def doCapture(self): logging.debug("Beginning capture") self.wb.setViewportSize(self.wb.mainFrame().contentsSize()) img = QtGui.QImage(self.wb.viewportSize(), QtGui.QImage.Format_ARGB32) painter = QtGui.QPainter(img) self.wb.mainFrame().render(painter) painter.end() img.save(self.filename) self.app.quit() def test(): """Run a simple capture""" app = QtGui.QApplication([]) c = Capturer("http://www.google.com", "google.png", app) c.capture() logging.debug("About to run exec_") app.exec_() DEBUG:root:Load http://www.google.com QObject::connect: Cannot connect (null)::configurationAdded(QNetworkConfiguration) to QNetworkConfigurationManager::configurationAdded(QNetworkConfiguration) QObject::connect: Cannot connect (null)::configurationRemoved(QNetworkConfiguration) to QNetworkConfigurationManager::configurationRemoved(QNetworkConfiguration) QObject::connect: Cannot connect (null)::configurationUpdateComplete() to QNetworkConfigurationManager::updateCompleted() QObject::connect: Cannot connect (null)::onlineStateChanged(bool) to QNetworkConfigurationManager::onlineStateChanged(bool) QObject::connect: Cannot connect (null)::configurationChanged(QNetworkConfiguration) to QNetworkConfigurationManager::configurationChanged(QNetworkConfiguration) Process Python segmentation fault (this last line is comes from emacs) 
+4
source share
2 answers

You need to handle QApplication outside of the test functions, sort of like a singleton (it really does fit here).

What you can do is check if QtCore.qApp is something (or if QApplication.instance () returns None or something else) and then create qApp, otherwise use global.

It will not be destroyed after your test () function, because PyQt stores the application somewhere.

If you want to be sure that this is correct, just set up a lazily initialized singleton for it.

+2
source

A QApplication should only be initialized once! It can be used by as many instances of Capture as possible, but you must run them in mainloop. See: https://doc.qt.io/qt-4.8/qapplication.html

You can also try "del app" after "app.exec_", but I'm not sure about the results. (Your original code works fine on my system)

I would use urllib instead of webkit:

 import urllib class Capturer: def capture(self, s_url, s_filename): s_file_out, httpmessage = urllib.urlretrieve(s_url, s_filename, self.report) def report(self, i_count, i_chunk, i_size): print('retrived %5d of %5d bytes' % (i_count * i_chunk, i_size)) def test(): c = Capturer() c.capture("http://www.google.com/google.png", "google1.png") c.capture("http://www.google.com/google.png", "google2.png") if __name__ == '__main__': test() 
+1
source

All Articles