使用Multiprocessing.pool进行PyQt奇怪的行为

时间:2017-07-23 01:40:06

标签: python qt pyqt python-multiprocessing

目前我正在尝试在一个线程内启动一个池,在这个池中我将创建Qt的QWebEnginePage的实例。

有两件事正在发生,而这些事情似乎正在发生。

第一:

它通过列表进行迭代的方式并不准确(要么跳过某些条目,要么它没有排序(不确定它是如何排序的) ))

第二

循环挂起,意味着一切都停止了,似乎我无能为力。

from multiprocessing.pool import Pool
from multiprocessing import Process

from threading import Thread
from PyQt5.Qt import *


class Webkit(QWebEnginePage):
    def __init__(self):
        self.app = QApplication([])

        super(Webkit, self).__init__()
        self.loadFinished.connect(self.pageFinishedLoading)

    def loadUrl(self, url):
        self.load(QUrl(url))
        self.app.exec()

    def pageFinishedLoading(self):
        self.app.quit()

def first():
    """Thread + Process"""
    #Thread(target=lambda: Process(target=second().foo()).start(), daemon=False).start()

    """Thread"""
    Thread(target=second().foo()).start()

    """Process"""
    #Process(target=second().foo()).start()


class second:
    def foo(self):
        count = 10

        print("Starting pool")
        with Pool(1) as pool:
            pool.map(final, range(count))

        print("Starting process")
        for x in range(count):
            p = Process(target=final, args=(x, ))
            p.start()
            p.join()

        print("Finished")

def final(a):
    print("Now creating webkit", a)
    wk = Webkit()
    wk.loadUrl("https://google.com")

if __name__ == '__main__':
    app = QApplication([])

    first()

    app.exec()

输出:

Starting pool
Now creating webkit 0
Now creating webkit 1
Now creating webkit 3
Now creating webkit 4
Now creating webkit 6
Now creating webkit 7
Now creating webkit 9

预期产出:

Starting pool
Now creating webkit 0
Now creating webkit 1
Now creating webkit 2
Now creating webkit 3
Now creating webkit 4
Now creating webkit 5
Now creating webkit 6
Now creating webkit 7
Now creating webkit 8
Now creating webkit 9

Starting process
Now creating webkit 0
Now creating webkit 1
Now creating webkit 2
Now creating webkit 3
Now creating webkit 4
Now creating webkit 5
Now creating webkit 6
Now creating webkit 7
Now creating webkit 8
Now creating webkit 9

Finished

编辑:for循环使其成为破坏的游泳池

1 个答案:

答案 0 :(得分:0)

我无法弄清楚任何真正的解决方案,所以我为它做了一个黑客,它并不漂亮,但它的工作几乎和普通的游泳池一样。它为每个进程创建了一个额外的进程,这意味着它将使用额外的内存,但除此之外它应该没问题。

如果有人有更好的解决方案,请发布:)

import multiprocessing as mp
from multiprocessing.pool import Pool, starmapstar
import itertools

def caller(func, *args):
    try: length = len(*args)
    except TypeError: length = 1
    p = mp.Process(target=func, args=tuple(*args) if length > 1 else (*args, ))
    p.start()
    return p.join()  # This will only return None



class NoDaemonProcess(mp.Process):
    # make 'daemon' attribute always return False
    def _get_daemon(self):
        return False
    def _set_daemon(self, value):
        pass
    daemon = property(_get_daemon, _set_daemon)


class MyPool(Pool):
    Process = NoDaemonProcess

    def _map_async(self, func, iterable, mapper, chunksize=None, callback=None, error_callback=None):
        iterable = zip(itertools.repeat(func), iterable)
        mapper = starmapstar
        func = caller
        return super(MyPool, self)._map_async(func, iterable, mapper, chunksize, callback, error_callback)