在后台运行该函数 - 如何? Python 和 PyQT

发布于 2024-12-11 02:16:41 字数 723 浏览 0 评论 0原文

我有一个用 Python 编写的相对较大的应用程序,并使用 PyQT 作为 GUI 前端。整个应用程序位于一个类、一个文件中。

这是一个示例代码:

class Application(QMainWindow):
  def __init__(self):
    super(etc...)

    self.connect(self.mainBtn, SIGNAL("clicked()"), self.do_stuff)

  def do_stuff(self):
    <checking some parameters>
    else:
      do_some_other_long_stuff()


  def do_some_other_long_stuff(self):
     500 lines of code of stuff doing

然而,这就是问题:当我单击 mainBtn 时,一切都很顺利,除了 GUI 类型冻结 - 在执行该功能之前我无法执行任何其他操作(并且它是一个网络抓取工具,因此需要相当多的时间)。当函数 do_some_other_long_stuff 结束时,一切恢复正常。这真是令人恼火。

有没有办法以某种方式“后台” do_some_other_stuff 进程?我研究了 QThreads,似乎它就是这样做的,但是这需要我重写基本上所有的代码,将我的程序的一半放在不同的类中,因此必须更改所有变量名称(当从 GUI 获取变量时)类并将其放入工人阶级)

I have a relatively large application written in Python and using PyQT as a GUI frontend. The entire application is in one class, in one file.

Here's an example code:

class Application(QMainWindow):
  def __init__(self):
    super(etc...)

    self.connect(self.mainBtn, SIGNAL("clicked()"), self.do_stuff)

  def do_stuff(self):
    <checking some parameters>
    else:
      do_some_other_long_stuff()


  def do_some_other_long_stuff(self):
     500 lines of code of stuff doing

However, this is the problem: when I click the mainBtn, everything goes fine, except the GUI kind of freezes - I can't do anything else until the function is performed (and it's a web scraper so it takes quite a bit of time). When the function do_some_other_long_stuff ends, everything goes back to normal. This is really irritating.

Is there a way to somehow "background" the do_some_other_stuff process? I looked into QThreads and it seems it does just that, however that would require me to rewrite basically all of code, put half of my program in a different class, and therefore have to change all the variable names (when getting a variable from GUI class and putting it in working class)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一抹淡然 2024-12-18 02:16:41

重复使用不同线程处理gui
如何跟踪Python 中的线程进度而不冻结 PyQt GUI? 等。

您的 do_stuff() 函数需要启动计算线程然后返回。多线程是在单个进程中运行多个活动的名称 - 根据定义,如果“在后台”发生某些事情,它就会在单独的线程上运行。但是您不需要将函数拆分为不同的类来使用线程,只需确保计算函数不会对 GUI 执行任何操作,并且主线程不会调用计算线程使用的任何函数即可。

编辑 10/23:这是一个在单个类中运行线程的愚蠢示例 - 语言或线程库中没有任何内容需要为每个线程使用不同的类。这些示例可能使用单独的类进行处理,以说明良好的模块化编程。

from tkinter import *
import threading

class MyApp:
    def __init__(self, root):
        self.root = root
        self.timer_evt = threading.Event()
        cf = Frame(root, borderwidth=1, relief="raised")
        cf.pack()
        Button(cf, text="Run", command=self.Run).pack(fill=X)
        Button(cf, text="Pause", command=self.Pause).pack(fill=X)
        Button(cf, text="Kill", command=self.Kill).pack(fill=X)

    def process_stuff(self):        # processing threads
        while self.go:
            print("Spam... ")
            self.timer_evt.wait()
            self.timer_evt.clear()

    def Run(self):                  # start another thread
        self.go = 1
        threading.Thread(target=self.process_stuff, name="_proc").start()
        self.root.after(0, self.tick)

    def Pause(self):
        self.go = 0

    def Kill(self):                 # wake threads up so they can die
        self.go = 0
        self.timer_evt.set()

    def tick(self):
        if self.go:
            self.timer_evt.set()    # unblock processing threads
            self.root.after(1000, self.tick)

def main():
    root = Tk()
    root.title("ProcessingThread")
    app = MyApp(root)
    root.mainloop()

main()

Duplicate of Handling gui with different threads,
How to keep track of thread progress in Python without freezing the PyQt GUI?, etc.

Your do_stuff() function needs to start up the computing thread and then return. Multi-threading is the name given to running multiple activities in a single process - by definition if something is going on "in the background", it's running on a separate thread. But you don't need to split functions into a different classes to use threads, just be sure that the computing functions don't do anything with the GUI and the main thread doesn't call any of the functions used by the computing thread.

EDIT 10/23: Here's a silly example of running threads in a single class - nothing in the language or the threading library requires a different class for each thread. The examples probably use a separate class for processing to illustrate good modular programming.

from tkinter import *
import threading

class MyApp:
    def __init__(self, root):
        self.root = root
        self.timer_evt = threading.Event()
        cf = Frame(root, borderwidth=1, relief="raised")
        cf.pack()
        Button(cf, text="Run", command=self.Run).pack(fill=X)
        Button(cf, text="Pause", command=self.Pause).pack(fill=X)
        Button(cf, text="Kill", command=self.Kill).pack(fill=X)

    def process_stuff(self):        # processing threads
        while self.go:
            print("Spam... ")
            self.timer_evt.wait()
            self.timer_evt.clear()

    def Run(self):                  # start another thread
        self.go = 1
        threading.Thread(target=self.process_stuff, name="_proc").start()
        self.root.after(0, self.tick)

    def Pause(self):
        self.go = 0

    def Kill(self):                 # wake threads up so they can die
        self.go = 0
        self.timer_evt.set()

    def tick(self):
        if self.go:
            self.timer_evt.set()    # unblock processing threads
            self.root.after(1000, self.tick)

def main():
    root = Tk()
    root.title("ProcessingThread")
    app = MyApp(root)
    root.mainloop()

main()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文