簡體   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