Как мне правильно закрыть QtApplication PyQt?

#python #pyqt

#python #pyqt

Вопрос:

Я не знаю самого главного о Qt, но я пытаюсь быть нахальным и заимствовать код из другого места (http://lateral.netmanagers.com.ar/weblog/posts/BB901.html#disqus_thread ). 😉

У меня проблема. Когда я запускаю test () в первый раз, все работает гладко. Однако, когда я запускаю его во второй раз, я получаю неприятные сбои в сегменте. Я подозреваю, что проблема в том, что я неправильно завершаю работу с qt. Что я должен изменить в этой программе, чтобы она работала несколько раз? Заранее спасибо!

 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)
  

Комментарии:

1. Итак, вы хотите писать код, копируя чужую работу, в то время как вы не понимаете, что именно копируете?

2. Довольно разумно позаимствовать код GPL для небольшого скрипта, когда рассматриваемый код был специально предоставлен для этой цели. Это очень похоже на использование библиотеки, за исключением того, что библиотека не работает, и я пытаюсь выяснить, как это исправить.

3. Я запустил его, и оно отлично сработало. (после добавления импорта, который вы пропустили.)

4. Hmmm…it у меня все еще не работает… privatepaste.com/7b922e6703

5. Почему вы хотите инициализировать / выключить Qt несколько раз в своем приложении? Если все, что вам нужно, это функция, которая захватывает веб-страницу и возвращает только по завершении, это может быть выполнено без нескольких инициализаций / завершений работы Qt.

Ответ №1:

Вам нужно обрабатывать QApplication вне тестовых функций, вроде как singleton (здесь это действительно уместно).

Что вы можете сделать, так это проверить, работает ли QtCore.qApp — это что-то (или если QApplication.instance () возвращает None или что-то еще) и только после этого создайте свое qApp, в противном случае используйте глобальное.

Оно не будет уничтожено после вашей функции test (), поскольку PyQt где-то хранит приложение.

Если вы хотите быть уверены, что оно обрабатывается правильно, просто настройте для него лениво инициализированный синглтон.

Комментарии:

1. Я также столкнулся с этой проблемой при попытке вызвать графический интерфейс несколько раз. Решение состояло в том, чтобы создать QApplication только один раз и передать его в инициализацию GUI.

Ответ №2:

QApplication должно быть инициализировано только один раз! Его может использовать любое количество экземпляров Capture, сколько вам угодно, но вы должны запускать их в mainloop. Смотрите:https://doc.qt.io/qt-4.8/qapplication.html

Вы также могли бы попробовать «удалить приложение» после «app.exec_», но я не уверен в результатах. (Ваш исходный код отлично работает в моей системе)

Я бы использовал urllib вместо 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 ] of ] 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()