为什么该函数不运行?
好吧,我的代码有多个问题:
- 当按住组合框中选择的键时,它会不断打印“您按下了它”,有没有办法避免这种情况?
- 当我按下设置热键时,标签发生变化,但 process() 中的 while 循环没有变化,它应该执行任务过程,但我将其简化为打印这个问题。
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")
一直在修改它,发现了更多问题
,我最终解决了这个问题,但是当它打印运行
时,我似乎无法阻止它
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)
Ok so I have multiple problems with the code under:
- when the key chosen in the Combo Box is held down, it keeps printing "You Pressed It", is there a way to avoid this?
- When I press the set hotkey, the label changes but the while loop in the process() doesnt, its suppose to do a process of tasks but I simplified it to print for this question.
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")
Been tinkering with it and found more problems
I ended up with this but while its printing run
I cant seem to stop it
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Python 脚本通常是线性的。你按顺序做事,然后退出。
在 tkinter 程序中,您的代码由三部分组成。
mainloop
中时从tkinter
调用的函数/方法。因此,在
tkinter
程序中,大部分代码都是mainloop
中的访客。它是为了响应事件而被分成小块执行的。这是一种完全不同的程序。早在 Web 服务器和框架中变得很酷之前,它就被称为“事件驱动”或“基于消息”编程。那么,您可以将脚本集成到
tkinter
程序中吗?是的,这是可能的。基本上有三种方法可以做到这一点;
after
调用。这涉及对代码的最大程度的重组。为了保持 GUI 的响应能力,事件处理程序(如超时)不应花费太长时间; 50 毫秒似乎是一个合理的上限。threading.Thread
和multiprocessing.Process
的 API 在设计上几乎相同)。最大的区别是进程之间的通信必须通过例如队列或管道显式完成。使用额外线程时必须考虑一些事项,尤其是在
tkinter
程序中。1) Python 版本
您需要使用 Python 3。这在 Python 2 中无法正常工作,原因超出了本答案的范围。 Python 3 中更好的线程抢占是其中的一个重要部分。
2) 多线程 tkinter 构建
tkinter
(或者更确切地说是底层的tcl
解释器)需要在启用线程的情况下构建。我猜想,ms-windows 的官方python.org
版本是这样的,但除此之外。在某些类 UNIX 系统(例如 Linux 或 *BSD)上,程序包/端口系统为您提供了一个选择。3) 将代码放入函数
您需要将原始脚本的核心包装在函数中,以便可以在线程中启动它。
4) 使函数对线程友好
如果线程花费太长时间,您可能希望能够中断该线程。所以你必须对其进行调整以定期检查它是否应该继续。检查名为
run
的全局是否为True
是一种方法。请注意,threading
API 不允许仅允许您终止线程。5 多线程的常见危险
同时从两个线程修改小部件或全局变量时必须小心。
在撰写本文时,Python GIL 可以在这方面为您提供帮助。由于它确保一次只有一个线程正在执行 Python 字节码,因此可以在单个字节码中完成的任何更改作为副作用都是多线程安全的。
例如,看
modify
函数中对一个全局的修改:看看新列表是如何单独构建的,只有完成后才分配给全局。 (这并非偶然。)
只需一条字节码指令 (
STORE_GLOBAL
) 即可将全局变量设置为新创建的列表。因此,data
的值在任何时候都不能含糊不清。但很多事情都需要多个字节码。因此,一个线程在修改变量或小部件时有可能被另一个线程抢占。机会有多大取决于这些情况发生的频率以及持续的时间。
IIRC,目前每 15 毫秒就有一个线程被抢占。
因此,需要比这更长的时间的更改保证会被抢占。任何删除 I/O GIL 的任务也是如此。
因此,如果您发现奇怪的事情发生,请确保使用
Lock
来规范对共享资源的访问。例如,如果某个小部件或变量仅从一个线程修改,并且仅从所有其他线程读取,那么它会有所帮助。
A Python script is generally linear. You do things in sequence and then you exit.
In a
tkinter
program, your code consists of three things.tkinter
when it is in themainloop
.So in a
tkinter
program most of your code is a guest in themainloop
. Where it is executed in small pieces in reaction to events. This is a completely different kind of program. It was called event-driven or message based programming long before that became cool in web servers and frameworks.So, can you integrate a script in a
tkinter
program? Yes, it is possible.There are basically three ways you can do it;
after
timeouts. This involves the most reorganization of your code. To keep the GUI responsive, event handlers (like timeouts) should not take too long; 50 ms seems to be a reasonable upper limit.threading.Thread
andmultiprocessing.Process
are almost the same by design). The largest difference is that communication between processes has to be done explicitly via e.g.Queue
orPipe
.There are some things that you have to take into account when using extra threads, especially in a
tkinter
program.1) Python version
You need to use Python 3. This will not work well in Python 2 for reasons that are beyond the scope of this answer. Better preemption of threads in Python 3 is a big part of it.
2) Multithreaded tkinter build
The
tkinter
(or rather the underlyingtcl
interpreter) needs to be built with threading enabled. I gather that the officialpython.org
builds for ms-windows are, but apart from that YMMV. On some UNIX-like systems such as Linux or *BSD the packages/ports systems gives you a choice in this.3) Make your code into a function
You need to wrap up the core of your original script in a function so you can start it in a thread.
4) Make the function thread-friendly
You probably want to be able to interrupt that thread if it takes too long. So you have to adapt it to check regularly if it should continue. Checking if a global named
run
isTrue
is one method. Note that thethreading
API does not allow you to just terminate a thread.5 The normal perils of multithreading
You have to be careful with modifying widgets or globals from both threads at the same time.
At the time of writing, the Python GIL helps you here. Since it assures that only one thread at a time is executing Python bytecode, any change that can be done in a single bytecode is multithreading safe as a side effect.
For example, look at the modification of a global in the
modify
function:See how the new list is built separately, and only when it is comple is it assigned to the global. (This was not by accident.)
It takes only a single bytecode instruction (
STORE_GLOBAL
) to set a global variable to a newly created list. So at no point can the value ofdata
be ambiguous.But a lot of things take more then one bytecode. So there is a chance that one thread is preempted in favor of the other while it was modifying a variable or widget. How big of a chance that is depends on how often these situations happen and how long they take.
IIRC, currently a thread is preempted every 15 ms.
So an change that takes longer than that is guaranteed to be preempted. As is any task that drops the GIL for I/O.
So if you see weird things happening, make sure to use
Lock
s to regulate access to shared resources.It helps if e.g. a widget or variable is only modified from one thread, and only read from all the other threads.
处理密钥的一种方法是将其变成两阶段循环:
One way to handle your key is to turn it into a two-phase loop: