如何在不获取新 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。经过一些调试后,我验证了 运行ning 代码的 PID 发生了变化。调用回调函数后,gui PID 会发生变化,app PID 也会发生变化,所以我相信它可以正常工作,但我不知道如何解决这个问题。
从我试图解决这个问题的时间来看,我相信我忽略了一些非常简单的方法来实现我的目标。提前致谢!
我认为您的问题是回调发生在另一个线程上。另一个线程对您的 GUI 一无所知。对 GUI 的所有更改都需要在主线程上进行。
尝试让 Api 只返回一个值。您的其他代码需要等待返回该值,然后更新 GUI。
GUI 和异步代码变得有点难看。
我最终得到了一个队列和一个线程以及进程,所以现在线程不断从队列中获取结果 while True
并在值发生变化时调用回调。真是一段旅程。
不是一个优雅的解决方案,但暂时解决了我的问题。
我在一个 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。经过一些调试后,我验证了 运行ning 代码的 PID 发生了变化。调用回调函数后,gui PID 会发生变化,app PID 也会发生变化,所以我相信它可以正常工作,但我不知道如何解决这个问题。
从我试图解决这个问题的时间来看,我相信我忽略了一些非常简单的方法来实现我的目标。提前致谢!
我认为您的问题是回调发生在另一个线程上。另一个线程对您的 GUI 一无所知。对 GUI 的所有更改都需要在主线程上进行。
尝试让 Api 只返回一个值。您的其他代码需要等待返回该值,然后更新 GUI。
GUI 和异步代码变得有点难看。
我最终得到了一个队列和一个线程以及进程,所以现在线程不断从队列中获取结果 while True
并在值发生变化时调用回调。真是一段旅程。
不是一个优雅的解决方案,但暂时解决了我的问题。