Python多进程回调

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

Python multprocessing callback

问题

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

  1. import multiprocessing
  2. import queue
  3. import collections
  4. import gi
  5. gi.require_version("Gtk", "3.0")
  6. from gi.repository import GLib, Gtk
  7. Msg = collections.namedtuple("Msg", ["event", "args"])
  8. class BaseProcess(multiprocessing.Process):
  9. "A process backed by internal queues for simple messaging"
  10. def __init__(self, *args, **kwargs):
  11. super().__init__(*args, **kwargs)
  12. self.requests = multiprocessing.Queue()
  13. self.responses = multiprocessing.Queue()
  14. def send(self, event, *args, finished_callback=None):
  15. "Puts the event and args as a `Msg` on the requests queue"
  16. msg = Msg(event, args)
  17. self.requests.put(msg)
  18. GLib.timeout_add(100, self._monitor_process, finished_callback)
  19. def run(self):
  20. while True:
  21. event, args = self.requests.get()
  22. if event == "quit":
  23. break
  24. handler = getattr(self, "do_%s" % event, None)
  25. if not handler:
  26. raise NotImplementedError("Process has no handler for [%s]" % event)
  27. msg = handler(*args)
  28. self.responses.put(msg)
  29. def _monitor_process(self, finished_callback):
  30. print(f"in _monitor_process {finished_callback}", flush=True)
  31. try:
  32. result = self.responses.get(False)
  33. if finished_callback is not None:
  34. finished_callback(result)
  35. except queue.Empty:
  36. return GLib.SOURCE_CONTINUE
  37. return GLib.SOURCE_REMOVE
  38. class MyProcess(BaseProcess):
  39. "test process class"
  40. def do_sum(self, arg1, arg2):
  41. "test method"
  42. print(f"do_sum {arg1 + arg2}", flush=True)
  43. return arg1 + arg2
  44. def finished_callback(result):
  45. print(f"result {result}", flush=True)
  46. Gtk.main_quit()
  47. if __name__ == "__main__":
  48. process = MyProcess()
  49. process.start()
  50. process.send('sum', 1, 2, finished_callback=finished_callback)
  51. 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:

  1. import multiprocessing
  2. import queue
  3. import collections
  4. import gi
  5. gi.require_version("Gtk", "3.0")
  6. from gi.repository import GLib, Gtk
  7. Msg = collections.namedtuple("Msg", ["event", "args"])
  8. class BaseProcess(multiprocessing.Process):
  9. "A process backed by internal queues for simple messaging"
  10. def __init__(self, *args, **kwargs):
  11. super().__init__(*args, **kwargs)
  12. self.requests = multiprocessing.Queue()
  13. self.responses = multiprocessing.Queue()
  14. def send(self, event, *args, finished_callback=None):
  15. "Puts the event and args as a `Msg` on the requests queue"
  16. msg = Msg(event, args)
  17. self.requests.put(msg)
  18. GLib.timeout_add(100, self._monitor_process, finished_callback)
  19. def run(self):
  20. while True:
  21. event, args = self.requests.get()
  22. if event == "quit":
  23. break
  24. handler = getattr(self, "do_%s" % event, None)
  25. if not handler:
  26. raise NotImplementedError("Process has no handler for [%s]" % event)
  27. msg = handler(*args)
  28. self.responses.put(msg)
  29. def _monitor_process(self, finished_callback):
  30. print(f"in _monitor_process {finished_callback}", flush=True)
  31. try:
  32. result = self.responses.get(False)
  33. if finished_callback is not None:
  34. finished_callback(result)
  35. except queue.Empty:
  36. return GLib.SOURCE_CONTINUE
  37. return GLib.SOURCE_REMOVE
  38. class MyProcess(BaseProcess):
  39. "test process class"
  40. def do_sum(self, arg1, arg2):
  41. "test method"
  42. print(f"do_sum {arg1 + arg2}", flush=True)
  43. return arg1 + arg2
  44. def finished_callback(result):
  45. print(f"result {result}", flush=True)
  46. Gtk.main_quit()
  47. if __name__ == "__main__":
  48. process = MyProcess()
  49. process.start()
  50. process.send('sum', 1, 2, finished_callback=finished_callback)
  51. 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:

  1. if __name__ == "__main__":
  2. process = MyProcess()
  3. process.daemon = True
  4. process.start()
  5. process.send('sum', 1, 2, finished_callback=finished_callback)
  6. 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:

确定