繁体   English   中英

如何在不获取新 PID 的情况下从 multiprocessing.Process 调用主进程中的方法?

[英]how to call method in the main process from a multiprocessing.Process without getting a new PID?

我在 python 应用程序中工作,用户应该能够输入查询并从 api 获取结果列表。 输入和结果都应该在 gui 中发生。

这应该在用户键入时发生(将来会出现一些反跳),因此用户应该能够查询“foo”并且应该触发对 api 的调用,但是如果用户改变主意并且现在想要查询“bar”,他应该能够更改他的查询之前的 api 调用是否结束。

我能够让它同步工作,其中 api 调用会阻止整个应用程序,直到它完成。 我这样做了(简化):

class Api:
    def get_results(self, query):
        return self.api.results(query)
    ...


class App:
    def __init__(self):
        self.gui = None
        self.api = None

    def get_results(self, query):
        self.api = Api()
        results = self.api.get_results
        self.gui.render(results)
    ...


class Gui(tk.Frame):
    def __init__(self, root, app, *args, **kwargs):
        tk.Frame.__init__(self, root, *args, **kwargs)
        self.root = root
        self.root.attributes('-type', 'dialog')
        self.app = app
        self.app.gui = self

    def render(self, results)
        # render results

为了让它异步工作,我想我应该在一个单独的线程或进程中运行调用,然后每次用户在 gui 中更改查询时杀死它并产生一个新的。 因此,我将 Api class 更改为从multiprocessing.Process继承,使用对应用程序实例的引用来初始化它,并添加一个方法来在初始化它的应用程序实例中运行回调。 有点像这样:

class Api(multiprocessing.Process):
    def __init__(self, app, query, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.app = app
        self.query = query
        self.start()

    def get_results(self, query):
        return self.api.results(query)
    
    def run(self):
        results = self.get_results
        self.app.callback(results)


class App:
    def __init__(self):
        self.gui = None
        self.api = None

    def get_results(self, query):
        if self.api:
            self.api.kill()
        self.api = Api(self, query)
    
    def callback(self, results):
        self.gui.render(results)


class Gui(tk.Frame):
    def __init__(self, root, app, *args, **kwargs):
        tk.Frame.__init__(self, root, *args, **kwargs)
        self.root = root
        self.root.attributes('-type', 'dialog')
        self.app = app
        self.app.gui = self

    def render(self, results)
        # render results

如果我使用一些打印语句运行此代码,我可以看到它确实工作正常,使用正确的值调用回调,但由于某种原因没有更新 gui。 经过一些调试,我验证了运行代码的 PID 发生了变化。 一旦回调 function 被调用,gui PID 和应用程序 PID 也会发生变化,所以我相信它有点工作,但我不知道解决这个问题。

从我试图解决这个问题的时间来看,我相信我忽略了一些非常简单的方法来实现我的目标。 提前致谢!

我相信你的问题是回调发生在另一个线程上。 其他线程对您的 GUI 一无所知。 对 GUI 的所有更改都需要在主线程上进行。

尝试让 Api 只返回一个值。 您的其他代码需要等待返回该值,然后更新 GUI。

GUI 和异步代码有点难看。

我最终得到了一个队列和一个线程以及进程,所以现在线程while True不断从队列中获取结果,并在值发生变化时调用回调。 相当的旅程。

不是一个优雅的解决方案,但现在解决了我的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM