【问题标题】:python thread data manipulationpython线程数据操作
【发布时间】:2021-10-05 10:40:20
【问题描述】:

我正在尝试从主函数处理线程中的一些数据。我在修改一些变量时面临的问题,这些变量是在线程上运行的函数的一部分。

所以我试图在线程中运行基于 Tkinter 的 GUI 循环,以确保它始终运行。并且想在main函数执行中修改一些状态对应的标签。我面临一个问题,它无法在主循环中找到标签变量,因为它是在线程上运行的函数的一部分。

下面是该方法的简化伪代码。请建议这是否是完成上述任务的正确方法,或者是否有更好更有效的方法。

import threading

def thread_func():
    i = 0
    while True:
        print('i from thread: ', i)

if __name__ == '__main__':
    t = threading.Thread(target=thread_func)
    t.start()
    
    while True:
        i += 1

实际缩小的简化代码

import threading
import tkinter as tk

def gui():
    window = tk.Tk()
    label = tk.Label(text='On')
    label.pack()
    window.mainloop()

if __name__ == '__main__':
    t = threading.Thread(target=gui)
    t.start()
    
    while True:
        label['text'] = 'Active'

错误:

Traceback (most recent call last):
  File "test.py", line 17, in <module>
    label['text'] = 'Active'
NameError: name 'label' is not defined

有没有更好的方法让 tkinter gui 始终打开并在循环中执行某些任务?

【问题讨论】:

  • 你的代码能解决你的问题吗?
  • 代码不起作用,因为它给我一个错误,更新问题中的错误并修复导入库名称
  • 可以使用global关键字(不推荐),或者创建一个类并在__init __函数中声明labelself.label = tk.Label (text = 'on')
  • @Deep 在使用tkinter 时不要使用线程,除非您知道风险。当从多个线程使用tkinter 时,我已经看到tkinter 崩溃python(没有回溯)。查看.after 脚本以安排对您的函数的调用。
  • @Deep 使用.after 脚本。查看here 的示例,其中我实现了tkinter 友好循环。

标签: python multithreading tkinter


【解决方案1】:

使用类和线程:

import tkinter


class Test(tkinter.Label):

    x = False

    def __init__(self):
        super().__init__()
        self.pack()
        self['text'] = 'On'

    def gui(self):
        if not self.x:
            self['text'] = 'Active'
            self.mainloop()
        else:
            self.mainloop()


if __name__ == '__main__':
    label = Test()
    while isinstance(label, Test):
        t = threading.Thread(target=label.gui())
        t.start()

【讨论】:

  • 如果我们不使用线程,那么我认为没有问题,主要问题是线程并且您删除了它!
  • 现在您正在调用label.gui(),然后将结果作为target 传递给threading.Thread。所以label.gui 不会在新线程中运行。
【解决方案2】:

当你在那里编写标签代码时,你会得到错误,因为当程序启动时它从创建线程开始,该线程只会在 tkinter 窗口关闭时结束,并且与之前的 thread_fuc 代码相同。并且你在 tkinter 窗口关闭后编写了标签代码。

上述问题将通过这样做解决:

import threading

def thread_func():
    while True:
        print('i from thread: ', i)

def tt():
    global i
    while True:
        i += 1

if __name__ == '__main__':
    i=0
    t = threading.Thread(target=thread_func)
    t.start()
    yt = threading.Thread(target=tt)
    yt.start()

使i 成为全局并并行运行 2 个函数。我们必须global 因为我们不能将一个函数的变量用于另一个函数。此外,我们在 2 个线程中运行 2 个函数。

对于@TheLizzard 建议的tkinter 文件,如果您想不断更改内容/想要使用循环,可以使用.after insted 或在tkinter 中使用线程。
这是实现它的基本示例:

import random
import tkinter as tk

app = tk.Tk()
app.geometry("200x220")

label = tk.Label(app, text="0")
label.pack()

def change(b=0):
    if b < 30:
        a = random.randrange(1, 7, 1)
        label.config(text=a)
        app.after(100, change, b+1)

b1 = tk.Button(app, text="Get New Number", command=change)
b1.pack()

app.mainloop()

关于它的更多解释,您可以访问here

【讨论】:

  • 仍然出现同样的错误:Traceback (most recent call last): File "test.py", line 17, in &lt;module&gt; label.config(text= 'Active') NameError: name 'label' is not defined
  • @Deep 是最后一次编辑清除,你为什么在那里使用线程?
  • 是的,这很清楚,但是执行我想要的任务的更好、更有效的方法是什么?除了线程来保持 gui 并能够在循环中修改某些内容之外,还有其他方法吗?
  • 我不想使用线程,如果有办法让 gui 持续运行,而我有另一个循环执行某些任务来更新 gui 上的状态。我不知道任何其他方法,所以如果你能帮助我提供任何有用的提示或建议。
  • 看起来不错。现在我将不得不投票赞成答案:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 2018-09-20
  • 2020-12-07
相关资源
最近更新 更多