2014-08-30 22 views
1

我試圖編寫一個簡單的解析器,它檢查一些網頁,如果這些網頁上的內容改變,然後腳本發送url到無頭webkit瀏覽器運行使用PySide綁定到Qt,並使屏幕截圖。我希望這個瀏覽器總是在後臺獨立進程中運行,等待url出現在隊列中。只要URL來臨,它會截圖,保存並返回等待狀態。PySide瀏覽器在一個單獨的過程

我嘗試實現這個代碼這種行爲(我切解析器部分):

import multiprocessing 
import sys 
from datetime import datetime 
from PySide import QtGui, QtWebKit, QtCore 

class Browser(QtWebKit.QWebPage): 
    def __init__(self, queue_in, queue_out): 
     self.app = QtGui.QApplication(sys.argv) 
     QtWebKit.QWebPage.__init__(self) 
     self.queue_out = queue_out 
     self.queue_in = queue_in 
     self.setViewportSize(QtCore.QSize(900, 900)) 
     self.mainFrame().setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) 
     self.mainFrame().setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff) 
     self.mainFrame().loadFinished.connect(self._makeScreenshot) 
     self.makeScreenshotOf() 

    def makeScreenshotOf(self): 
     self.mainFrame().setUrl(QtCore.QUrl.fromEncoded(self.queue_in.get())) 

    def _makeScreenshot(self): 
     image = QtGui.QImage(self.viewportSize(), QtGui.QImage.Format_ARGB32) 
     painter = QtGui.QPainter(image) 
     self.mainFrame().render(painter) 
     painter.end() 
     file_name = datetime.now().strftime("%Y-%m-%d %H-%M-%S-%f") + ".png" 
     image.save(file_name) 
     self.queue_out.put(file_name) 
     self.makeScreenshotOf() 

if __name__ == "__main__": 
    multiprocessing.set_start_method('spawn') 
    queue_in = multiprocessing.Queue() 
    queue_out = multiprocessing.Queue() 
    t = threading.Thread(target = Browser, args = (queue_in, queue_out)) 
    t.start() 
    queue_in.put(url) 

的問題是,在第一次運行過程中成功地保持擱置,等待URL出現在隊列中,但一旦它得到URL,過程只是停止,忽略Qt的連接

self.mainFrame().loadFinished.connect(self._makeScreenshot) 

的事情是,如果我直接從流程繼承

class Browser(multiprocessing.Process): 
    def __init__(self, queue_in, queue_out): 
     multiprocessing.Process.__init__(self) 
     self.queue_out = queue_out 
     self.queue_in = queue_in 
     self.app = QtGui.QApplication(sys.argv) 
     self.browser = QtWebKit.QWebPage() 
     ... 
if __name__ == "__main__": 
    queue_in = multiprocessing.Queue() 
    queue_out = multiprocessing.Queue() 
    b = Browser(queue_in, queue_out) 

然後連接不會被忽略,並且所有工作都完美無缺,但是作爲在瀏覽器進程中調用的副作用self.queue_in.get()也會阻止主進程(如果隊列爲空)。

問題:

  1. 爲什麼Qt的連接在第一種情況下不能正常工作和其他工作?
  2. 爲什麼在第二種情況下queue.get()阻塞主進程?如何防止這一點?

回答

1

看來,調用app.exec_()是必不可少的。現在一切正常。除了我得到

warning qapplication was not created in the main() 

儘管這一切的作品,無論如何,我決定把它移到一個單獨的過程中的主要

app = QtGui.QApplication(sys.argv) 
browser = Browser(queue_in, queue_out) 
app.exec_() 

和運行解析器的一部分。

UPD

提花如何在一個進程中運行的QApplication

class QtApp(QtGui.QApplication): 
""" 
docstring 
""" 
def __init__(self, args, url_queue, filename_queue): 
    QtGui.QApplication.__init__(self, args) 
    browser = Browser(url_queue, filename_queue) 
    self.exec_() 

browser_process = multiprocessing.Process(target=QtApp, 
              args=(sys.argv, url_queue, filename_queue)) 
2

Queue.get()如果隊列爲空,則阻止塊。使用get_nowait(),如果沒有任何內容會引發異常。

+0

嘛。但是我需要我的瀏覽器在這一點上繼續運行。所以在這種情況下,我需要在進程內部創建一個異常處理程序,並定期檢查隊列中是否有東西?也許。我也可以創建另一個解析部分的過程,不用擔心主進程被阻塞。這有點不是我想知道的。我更感興趣的是爲什麼會發生這種情況。但是,感謝您解決這個問題。 – 2014-08-31 00:52:56