2017-01-25 1 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

, 그래서 응용 프로그램을 종료하지 않습니다. – eyllanesc

+0

@eyllanesc 그렇다면 어떻게 app.quit()를 사용하지 않고 호출자에게 제어권을 되돌릴 수 있습니까? – GreySage

+0

코드를 재현 할 수 없기 때문에 전체 코드를 공유 할 수 있습니다. – eyllanesc

답변

0

QApplication 개체를 다시 만들거나 다시 사용하면 플랫폼 및/또는 사용중인 PyQt/PySide의 특정 버전에 따라 문제가 발생할 수 있습니다.

따라서 예제 이벤트 코드를 적용하여 응용 프로그램 이벤트 루프를 계속 종료하고 다시 시작하지 않고 로컬 이벤트 루프를 사용하도록했습니다. 이 로컬 루프는 페이지가로드되지 않으면 30 초 후에 시간이 초과되어야합니다. 원래 예제에서는 콘솔 응용 프로그램을 만들려고 시도하지만 잘못된 구문을 사용합니다. 그러나 전체 GUI 응용 프로그램은 웹 페이지를 렌더링하는 데 필요합니다 (실제로 시스템에서 코어를 덤프하는 경우). 이 코드는 Python2와 Python3을 PySide-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/']) 

출력 : 당신은 인스턴스를 생성하고 첫 번째 URL로 발생하는 렌더링 방법에 닫습니다 클래스의 생성자에서

$ python2 test.py 
loaded: [863822 bytes] http://en.wikipedia.org/wiki/Main_Page 
loaded: [1718852 bytes] http://stackoverflow.com/ 
관련 문제