不同的导入导致不同的错误

Different Imports Results in Different Errors

我正在使用 Tkinter 创建一个可以请求和接收消息的简单 GUI。

尝试在标签内显示消息,我试过这个:

from tkinter import *
from tkinter import ttk
from reqrep_server import *

root = Tk()
root.title("Server")

request = Button(root, text="Request")
request.grid(row=0, sticky=E)
request.bind("<Button-1>", main)

LabelRep = Label.config(root, text=response)
LabelRep.grid(row=1, sticky=E)

root.mainloop()

结果为:NameError: name 'response' is not defined

当我尝试时:

from tkinter import *
from tkinter import ttk
import reqrep_server

root = Tk()
root.title("Server")

request = Button(root, text="Request")
request.grid(row=0, sticky=E)
request.bind("<Button-1>", reqrep_server.main)

LabelRep = Label.config(root, text=reqrep_server.response)
LabelRep.grid(row=1, sticky=E)

root.mainloop()

发生这种情况:AttributeError: module 'reqrep_server' has no attribute 'response'

这只发生在 response 变量上,但不会发生在 main 函数上,因为它工作正常.

响应变量在 for 循环内:

reqrep_server

for request in range(1, 3):
        print("Sending request ", request,"...")
        socket.send_string("Sensor Data")
        msg_json = socket.recv()
        ds = json.loads(msg_json)
        response = "Sensor: %s :: Data: %s :: Client: %s" % (ds['sensor'], ds['data'], ds['client'])
        print("Received reply ", request, "[", response, "]")
        time.sleep(1)

main方法中。

如何解决错误并使其正常工作?

编辑:

对于那些需要回溯的人:

Traceback (most recent call last):
  File "C:\Users\tobiw\Documents\Python\Raspberry Pi\zmq\serverTTK.py", line 12, in <module>
    LabelRep = Label.config(root, text=reqrep_server.response)
AttributeError: module 'reqrep_server' has no attribute 'response'
[Finished in 0.3s with exit code 1]

两个错误都有相似的回溯和文件路径,只是错误类型不同。

要从另一个模块中的函数获取变量,它必须是全局变量

(reqrep_server.py)

import time

response = 'start value' # <-- it is global variable

def main():
    global response # <-- inform function to use global variable inside function
                    #      (instead of local one)

    for x in range(10):
        response = str(x)
        print(response)

        time.sleep(1)

然后它将运行没有错误

(main.py)

import tkinter as tk
import reqrep_server

root = tk.Tk()
root.title("Server")

label_rep = tk.Label(root, text=reqrep_server.response)
label_rep.pack()

request = tk.Button(root, text="Request", command=reqrep_server.main)
request.pack()

root.mainloop()

但它不会像您预期的那样工作。

您会在开始时在 Label 中看到 'start value',因为 text=reqrep_server.response 仅将值从 reqrep_server.response 复制到 text 一次 - 在开始时 - 稍后不会自动复制这个。

当您单击按钮时,它会冻结 GUI,因为它会阻止 mainloop 从系统获取 key/mouse 事件、将事件发送到小部件、更新小部件、重绘小部件等。

你必须在 main 中进行两次思考

  • 使用root.update()强制mainloop执行一个循环。
  • 使用label_rep['text'] = response更新标签中的文本

所以按钮应该使用 lambda

使用两个参数 rootlabel_rep 执行 main
command=lambda:reqrep_server.main(root, label_rep)

您将获得代码

(main.py)

import tkinter as tk
import reqrep_server

root = tk.Tk()
root.title("Server")

label_rep = tk.Label(root) # doesn't need text at start, text=reqrep_server.response)
label_rep.pack()

request = tk.Button(root, text="Request", command=lambda:reqrep_server.main(root, label_rep))
request.pack()

root.mainloop()

main必须使用它们

(reqrep_server.py)

import time

# doesn't need this: response = 'start value'

def main(master, label):
    # doesn't need this: global response

    for x in range(10):
        response = str(x)
        print(response)

        label['text'] = response # <-- update label
        master.update() # <-- run mainloop once

        time.sleep(1)

如果 main() 需要更多时间来工作,而 master.update() 执行频率较低,那么它会再次冻结 - 然后也许你应该 运行 main()分离 thread.