我尝试编写一个简单的解析器,它检查一些网页,如果这些页面上的内容发生更改,则脚本将 url 发送到 headless webkit 浏览器,该浏览器使用 PySide 绑定(bind)到 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()
在浏览器进程中调用也会阻塞主进程(如果队列为空)。
问题:
- 为什么 Qt 连接在第一种情况下不起作用,而在另一种情况下却工作?
- 为什么在第二种情况下,queue.get() 会阻塞主进程?如何防止这种情况发生?
最佳答案
如果队列为空,
Queue.get()
会阻塞。使用get_nowait() ,如果那里没有任何内容,则会引发异常。
关于python - PySide 浏览器位于单独的进程中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25587772/