You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python使用ProcessPoolExecutor多进程时实现Tkinter进度实时更新问题

Tkinter结合ProcessPoolExecutor实现多进程进度实时展示解决方案

核心问题原因

你提供的代码使用ProcessPoolExecutor不生效的核心原因如下:

  • Windows系统下Python多进程默认采用spawn启动模式,提交给进程池的可调用对象必须支持pickle序列化,原代码中work和save_values是定义在start_processing方法内的嵌套函数,无法被序列化,子进程无法正常接收并执行任务
  • 原代码多进程同时写入同一个txt文件时没有加锁,会出现写入内容错乱的问题

修复后可运行代码

import concurrent.futures
import tkinter
import tkinter.ttk
import multiprocessing
import random
import time

# 把内部函数移到全局作用域,支持序列化
def save_values(my_values, write_lock):
    # 加锁避免多进程写入冲突
    with write_lock:
        with open(f"example.txt", "a") as file:
            for v in my_values:
                file.write(str(v))
                file.write(" ")
            file.write("\n")

def work(my_values, my_queue, write_lock):
    my_progress = 0
    step = 100 / len(my_values)
    updated_values = []
    for v in my_values:
        time.sleep(0.5)
        updated_values.append(v + 1)
        my_progress += step
        my_queue.put(my_progress)
    save_values(updated_values, write_lock)


class App:
    def __init__(self, root):
        self.root = root
        # 新增多进程写入锁
        self.write_lock = multiprocessing.Lock()

        self.processes = 5
        self.percentage = []
        self.changing_labels = []
        self.queues = []
        self.values = []

        for i in range(self.processes):
            temp_percentage = tkinter.StringVar()
            temp_percentage.set("0 %")
            self.percentage.append(temp_percentage)

            temp_changing_label = tkinter.Label(self.root, textvariable=temp_percentage)
            temp_changing_label.pack()
            self.changing_labels.append(temp_changing_label)

            self.queues.append(multiprocessing.Queue())
            temp_value = []
            for ii in range(12):
                temp_value.append(random.randrange(10))
            self.values.append(temp_value.copy())

        self.start_processing()

    def start_processing(self):
        with concurrent.futures.ProcessPoolExecutor() as executor:
            results = [executor.submit(work, self.values[i], self.queues[i], self.write_lock)
                       for i in range(self.processes)]
            while True:
                results_done = [result.done() for result in results]

                if False in results_done:
                    for i in range(self.processes):
                        if not results_done[i]:
                            if not self.queues[i].empty():
                                temp_queue = self.queues[i].get()
                                self.percentage[i].set(f"{temp_queue:.2f} %")
                        else:
                            self.percentage[i].set("100 %")
                        self.root.update()
                else:
                    break
        self.root.destroy()


def main():
    root = tkinter.Tk()
    my_app = App(root)
    root.mainloop()


if __name__ == "__main__":
    main()

关键修改说明

  • 将原本嵌套在方法内的work、save_values函数移到全局作用域,满足多进程序列化要求
  • 新增multiprocessing.Lock作为多进程写入文件的锁,避免文件内容错乱
  • 未修改原代码的核心逻辑和main函数结构,符合你的需求

内容的提问来源于stack exchange,提问作者Kounabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 11:45:00