2017-01-25 9 views
1

私は、URLのリストか単一のURLのどちらかをとり、それらをレンダリングできるクラスを作ろうとしています。QApplicationを連続して実行できますか?

リストケースでは、すべてをレンダリングし、すべてのhtmlを含む辞書を使用可能にします。これは正常に動作します。

単一のケースでは、URLを受け取り、レンダリングし、htmlを属性として使用可能にして終了します。これは一度実行するとうまく動作しますが、2回以上試してみるとapp.exec_()を呼び出すとロックされます。

import sys 
from PySide.QtCore import * 
from PySide.QtGui import * 
from PySide.QtWebKit import QWebPage, QWebFrame 

class Renderer(QWebPage): 
    def __init__(self): 
     self.app = QCoreApplication.instance() 
     if self.app == None: 
      self.app = QApplication(sys.argv) 
      self.app.Type(QApplication.Tty) 
     QWebPage.__init__(self) 
     self.pages = [] 

    def start(self, urls): 
     #for lists 
     try: 
      self.loadFinished.disconnect() 
     except Exception: 
      pass 
     self.loadFinished.connect(self.listFinished) 
     self._urls = iter(urls) 
     self.fetchNext() 
     self.app.exec_() 

    def fetchNext(self): 
     #for lists 
     try: 
      url = next(self._urls) 
     except StopIteration: 
      return False 
     else: 
      self.mainFrame().load(QUrl(url)) 
     return True 

    def listFinished(self): 
     #for lists 
     html = self.processCurrentPage() 
     self.pages.append(html) 
     if not self.fetchNext(): 
      self.app.quit() 

    def processCurrentPage(self): 
     url = self.mainFrame().url().toString() 
     html = self.mainFrame().toHtml() 
     return html 

    def render(self, url): 
     try: 
      self.loadFinished.disconnect() 
     except Exception: 
      pass 
     self.loadFinished.connect(self.singleFinished) 
     self._url = url 
     self.mainFrame().load(QUrl(url)) 
     self.app.exec_() 

    def singleFinished(self): 
     print "singleFinished" 
     html = self.processCurrentPage() 
     self._html = html 
     self.app.quit() 

私がしようとしていることは可能ですか? render()を何度も呼び出せるように、このコードを修正するにはどうすればいいですか?私はちょうどリストベースのバージョンを使用する必要がありますか?

リストの大文字と小文字を同時に入力すると同じ問題が発生します。私はquit()の後にexec_()を呼び出すのが好きではないと確信していますが、これについてのドキュメントは見つかりませんでした。

+0

あなたのクラスのコンストラクタでインスタンスを作成して、それがアプリケーションを終了していないので、最初のURLで発生レンダリング方法、それを閉じます。 – eyllanesc

+0

@eyllanescしたがって、app.quit()を使用せずに呼び出し元に制御を戻すにはどうすればよいですか? – GreySage

+0

コードを再現できないため、コード全体を共有することができます。 – eyllanesc

答えて

0

QApplicationオブジェクトを再作成または再利用すると、プラットフォームや使用しているPyQt/PySideの特定のバージョンによって問題が発生することがあります。

したがって、アプリケーションイベントループを継続して終了して再起動するのではなく、ローカルイベントループを使用するようにサンプルコードを修正しました。このローカル・ループは、ページがロードされない場合に30秒後にタイムアウトする必要があります。元の例ではコンソールアプリケーションを作成しようとしていますが(間違った構文を使用しています)しかし、Webページをレンダリングするには完全なGUIアプリケーションが必要です(実際にはシステム上でコアダンプを行うだけです)。コードはPython2とPython3をPython-1.2.4とPyQt-4.12を使ってArchLinux(通常のコンソールから実行)でテストしました。

import sys 
from PySide.QtCore import * 
from PySide.QtGui import * 
from PySide.QtWebKit import QWebPage, QWebFrame 
# from PyQt4.QtCore import * 
# from PyQt4.QtGui import * 
# from PyQt4.QtWebKit import QWebPage, QWebFrame 

class Renderer(QWebPage): 
    def __init__(self): 
     self.app = QApplication.instance() 
     if self.app is None: 
      self.app = QApplication(sys.argv) 
     super(Renderer, self).__init__() 
     self.mainFrame().loadFinished.connect(self.handleLoadFinished) 
     self.loop = QEventLoop() 

    def render(self, urls): 
     self._urls = iter(urls) 
     self.fetchNext() 

    def fetchNext(self): 
     self.loop.exit(0) 
     try: 
      url = next(self._urls) 
     except StopIteration: 
      return False 
     else: 
      self.mainFrame().load(QUrl(url)) 
      timer = QTimer() 
      timer.setSingleShot(True) 
      timer.timeout.connect(lambda: self.loop.exit(1)) 
      timer.start(30000) 
      if self.loop.exec_() == 1: 
       print('url load timed out: %s' % url) 
     return True 

    def processCurrentPage(self): 
     url = self.mainFrame().url().toString() 
     html = self.mainFrame().toHtml() 
     print('loaded: [%d bytes] %s' % (self.bytesReceived(), url)) 

    def handleLoadFinished(self): 
     self.processCurrentPage() 
     self.fetchNext() 

if __name__ == '__main__': 

    r = Renderer() 
    r.render(['http://en.wikipedia.org/']) 
    r.render(['http://stackoverflow.com/']) 

出力:

$ python2 test.py 
loaded: [863822 bytes] http://en.wikipedia.org/wiki/Main_Page 
loaded: [1718852 bytes] http://stackoverflow.com/ 
関連する問題