好的,下面的代码有多个问题:
run = False
def press():
global run
while True:
if keyboard.read_key(hotCombo.get()):
print("You Pressed It")
run = not run
keyboard.wait(hotCombo.get())
if run == True:
status["text"]="Working"
else:
status["text"]="Not Working"
def process():
while run == True:
print("runnning")
一直在修补它,发现了更多的问题
我最终得到了这个,但当它打印run
时,我似乎无法阻止它。
def process():
global run
while True:
if keyboard.read_key(hotCombo.get()):
print("kijanbdsjokn")
run = not run
keyboard.wait(hotCombo.get())
if run == True:
status["text"]="Working"
else:
status["text"]="Not Working"
while run == True:
print("run")
time.sleep(1)
发布于 2022-03-19 00:01:58
我能问一下为什么我不能使用线程将tkinter集成到运行中的python脚本中吗?
Python脚本通常是线性的。你按顺序做事然后退出。
在tkinter
程序中,代码由三部分组成。
设置全局变量的窗口和widgets.
因此,在tkinter
程序中,大部分代码都是mainloop
中的来宾。在那里,它是小块执行,以回应事件。这是一个完全不同的节目。它被称为事件驱动或基于消息的编程,很久以前,它在web服务器和框架中变得很酷。
那么,您能在tkinter
程序中集成一个脚本吗?是的,这是可能的。基本上有三种方法可以做到;
after
超时来调用。这涉及到您的代码的大部分重组。为了保持GUI响应,事件处理程序(如超时)不应该花费太长时间;50 ms似乎是一个合理的上限。threading.Thread
和multiprocessing.Process
的API在设计上几乎相同)。最大的区别是进程之间的通信必须通过例如Queue
或Queue
显式地完成。在使用额外的线程时,特别是在tkinter
程序中,您必须考虑到一些事情。
1) Python版本
您需要使用Python 3,这在Python 2中不能很好地工作,原因超出了这个答案的范围。在Python 3中更好地抢占线程是其中的一个重要部分。
2)多线程tkinter构建
tkinter
(或者更确切地说是底层tcl
解释器)需要在启用线程的情况下构建。我想官方的python.org
是为ms-windows构建的,但除了这个YMMV之外。在一些类似UNIX的系统上,例如Linux或*BSD,包/端口系统在这方面提供了一个选择。
3)将代码变成函数
您需要将原始脚本的核心封装在一个函数中,这样就可以在线程中启动它。
4)使函数线程友好的
如果需要太长时间,您可能希望能够中断该线程。所以你必须调整它,以定期检查它是否应该继续。检查全局名为run
是否为True
是一种方法。请注意,threading
API不允许您只终止线程。
5多线程的正常危险
您必须小心同时从两个线程修改小部件或全局。
在编写本报告时,Python在这里帮助您。由于它确保一次只有一个线程正在执行Python字节码,因此在单个字节码中可以执行的任何更改都是多线程安全的,这是一个副作用。
例如,查看modify
函数中全局的修改:
In [1]: import dis
In [2]: data = []
Out[2]: []
In [3]: def modify():
...: global data
...: newdata = [1,2,3]
...: data = newdata
...:
In [4]: dis.dis(modify)
3 0 BUILD_LIST 0
2 LOAD_CONST 1 ((1, 2, 3))
4 LIST_EXTEND 1
6 STORE_FAST 0 (newdata)
4 8 LOAD_FAST 0 (newdata)
10 STORE_GLOBAL 0 (data)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
查看新列表是如何单独构建的,并且只有在组合时才将其分配给全局列表。(这不是偶然的。)
只需一个字节码指令(STORE_GLOBAL
)就可以将全局变量设置为新创建的列表。因此,data
的值在任何时候都不能模棱两可。
但是很多事情需要的不仅仅是一个字节码。因此,在修改变量或小部件时,一个线程有可能被抢占而对另一个线程有利。这是一个多大的机会,取决于这些情况发生的频率和时间。
IIRC,目前每15 ms抢占一条线程。因此,一个需要更长时间的改变肯定会被抢占。就像任何为了I/O丢弃吉尔的任务一样。
因此,如果您看到奇怪的事情发生,请确保使用Lock
来规范对共享资源的访问。
如果小部件或变量只从一个线程修改,而只从其他所有线程读取,则会有所帮助。
发布于 2022-03-18 22:53:14
处理密钥的一种方法是将其转换为一个两阶段循环:
def press():
global run
while True:
while not keyboard.read_key(hotCombo.get()):
time.sleep(0.2)
run = True
status["text"]="Working"
while keyboard.read_key(hotCombo.get()):
print("running")
time.sleep(0.2)
run == False
status["text"]="Not Working"
https://stackoverflow.com/questions/71535935
复制