Python多进程回调

huangapple go评论63阅读模式
英文:

Python multprocessing callback

问题

使用这个帖子作为灵感,我试图添加一个回调。我正在使用GLib.add_timeout来轮询结果,因为我想在Gtk应用中使用它。但是,main_quit()没有正确调用,因此在完成后以下代码挂起:

import multiprocessing
import queue
import collections
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk

Msg = collections.namedtuple("Msg", ["event", "args"])

class BaseProcess(multiprocessing.Process):
    "A process backed by internal queues for simple messaging"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.requests = multiprocessing.Queue()
        self.responses = multiprocessing.Queue()

    def send(self, event, *args, finished_callback=None):
        "Puts the event and args as a `Msg` on the requests queue"
        msg = Msg(event, args)
        self.requests.put(msg)
        GLib.timeout_add(100, self._monitor_process, finished_callback)

    def run(self):
        while True:
            event, args = self.requests.get()
            if event == "quit":
                break
            handler = getattr(self, "do_%s" % event, None)
            if not handler:
                raise NotImplementedError("Process has no handler for [%s]" % event)
            msg = handler(*args)
            self.responses.put(msg)

    def _monitor_process(self, finished_callback):
        print(f"in _monitor_process {finished_callback}", flush=True)
        try:
            result = self.responses.get(False)
            if finished_callback is not None:
                finished_callback(result)
        except queue.Empty:
            return GLib.SOURCE_CONTINUE
        return GLib.SOURCE_REMOVE

class MyProcess(BaseProcess):
    "test process class"

    def do_sum(self, arg1, arg2):
        "test method"
        print(f"do_sum {arg1 + arg2}", flush=True)
        return arg1 + arg2

def finished_callback(result):
    print(f"result {result}", flush=True)
    Gtk.main_quit()

if __name__ == "__main__":
    process = MyProcess()
    process.start()
    process.send('sum', 1, 2, finished_callback=finished_callback)
    Gtk.main()

如何防止代码挂起?

英文:

Using this post as inspiration, I am trying to add a callback. I am using GLib.add_timeout to poll for the result, as I want to use it in a Gtk app. However, the main_quit() is not called properly, and thus the following code hangs after finishing:

import multiprocessing
import queue
import collections
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk
Msg = collections.namedtuple("Msg", ["event", "args"])
class BaseProcess(multiprocessing.Process):
"A process backed by internal queues for simple messaging"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.requests = multiprocessing.Queue()
self.responses = multiprocessing.Queue()
def send(self, event, *args, finished_callback=None):
"Puts the event and args as a `Msg` on the requests queue"
msg = Msg(event, args)
self.requests.put(msg)
GLib.timeout_add(100, self._monitor_process, finished_callback)
def run(self):
while True:
event, args = self.requests.get()
if event == "quit":
break
handler = getattr(self, "do_%s" % event, None)
if not handler:
raise NotImplementedError("Process has no handler for [%s]" % event)
msg = handler(*args)
self.responses.put(msg)
def _monitor_process(self, finished_callback):
print(f"in _monitor_process {finished_callback}", flush=True)
try:
result = self.responses.get(False)
if finished_callback is not None:
finished_callback(result)
except queue.Empty:
return GLib.SOURCE_CONTINUE
return GLib.SOURCE_REMOVE
class MyProcess(BaseProcess):
"test process class"
def do_sum(self, arg1, arg2):
"test method"
print(f"do_sum {arg1 + arg2}", flush=True)
return arg1 + arg2
def finished_callback(result):
print(f"result {result}", flush=True)
Gtk.main_quit()
if __name__ == "__main__":
process = MyProcess()
process.start()
process.send('sum', 1, 2, finished_callback=finished_callback)
Gtk.main()

How can I prevent the code from hanging?

Edit: I see from this page that others have noted problems. How can I build a Gtk-based app to control long-running processes like scanners without blocking the main thread?

答案1

得分: 0

这段代码中,需要将以下部分翻译为中文:

"The threading docs for pyGObject" => "关于pyGObject的线程文档"
"lead me to the answer, which is to add process.daemon = True before starting the process:" => "指引我找到答案,即在启动进程前添加process.daemon = True:"
"if name == "main":" => "如果__name__ == "main":"
"process = MyProcess()" => "process = MyProcess()"
"process.daemon = True" => "process.daemon = True"
"process.start()" => "process.start()"
"process.send('sum', 1, 2, finished_callback=finished_callback)" => "process.send('sum', 1, 2, finished_callback=finished_callback)"
"Gtk.main()" => "Gtk.main()"

请注意,我已经将代码部分保持原样,只翻译了代码之外的文本。

英文:

The threading docs for pyGObject lead me to the answer, which is to add process.daemon = True before starting the process:

if __name__ == "__main__":
process = MyProcess()
process.daemon = True
process.start()
process.send('sum', 1, 2, finished_callback=finished_callback)
Gtk.main()

huangapple
  • 本文由 发表于 2023年2月16日 18:02:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定