我尝试编写一个简单的解析器,检查一些网页,如果这些页面上的内容发生了变化,那么脚本会将url发送到无头webkit浏览器,该浏览器使用PySide绑定到Qt并进行截屏。我希望这个浏览器始终在后台单独的进程中运行,等待url出现在队列中。一旦url到来,它就会截图,保存它然后返回等待。
我尝试使用此代码实现此行为(我剪切了解析器部分):
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)
问题是如果我直接从Process
继承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()
也会阻止主进程(如果队列为空)。
问题:
答案 0 :(得分:2)
Queue.get()
会阻塞。使用get_nowait(),如果那里没有任何内容,则会引发异常。
答案 1 :(得分: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))