Tkinter text updates take too long to load - python

i've got a working piece of code here, but when the if flag == True: statement completes, the playsound activates, but it takes roughly 3 seconds longer for the detectionLabel text to update. Can someone take a look at the code below and help recommend a way that I can help speed up the text updating process? Thanks!
def loop(addressField,url):
detectionLabel['text']="Scanning..."
flag = False
address = addressField.get()
def loopOver(flag):
print("loop")
flag,response = searchLoop(address,url,flag)
if flag == True:
print("Detected")
playsound.playsound('success.mp3')
detectionLabel['text']=f"DETECTED:\n{response}"
else:
detectionWindow.after(5000,lambda: loopOver(flag))
loopOver(flag)

Related

python - while loop structure

I need help to construct a working while loop.
my code goes like this
class Bot():
def __init__(self):
self.woke = False
while self.woke == False:
self.wake_word() # --> when it predicts wake word self.woke changes to True
while self.woke == True:
self.voice_recognition() # --> takes audio turns it to a spoke.txt file
break
self.chat() # --> reads the spoke.txt and finds a response
self.respond() # --> speaks the responds using pyttsx3
the code works perfectly but only for one time..it does what I want it to do but for once and then the script stops.
I need to run it until I give the command to stop it using
sys.exit(0) # in a function
meaning when it responses it starts listening again (self.voice_recognition() function) and again does the chat() and finds a respond().
Not exactly sure what you are looking for, but try this -
class Bot():
def __init__(self):
self.woke = False
while self.woke == False:
self.wake_word() # --> when it predicts wake word self.woke changes to True
while self.woke == True:
self.voice_recognition() # --> takes audio turns it to a spoke.txt file
self.woke=False
break
self.chat() # --> reads the spoke.txt and finds a response
self.respond() # --> speaks the responds using pyttsx3
I had a problem with the way I'm capturing audio.. (I had to close the stream).
what happened was that each time the voice_recognition() was called the stream was already open so the data didn't change and that causes an infinite loop inside the function which caused it to not work how it was supposed to
the final code the was correctly working is this
self.wake_word()
while True:
self.voice_recognition()
self.chat()
self.respond()
really simple and straight forward, the problem was with it the function not the while loop structure.
Thanks for anyone who took the time and tried to answer I'm sure your answers / comments were correct as this wasn't about the while loop structure yet a simple unrecognized missing code.

How to add hotkey in Python?

I'm making a bot for a game and I want to call the function when I press hotkey. I already tried some solutions but it is not good. Here is my code:
def start():
while True:
if keyboard.is_pressed('alt+s'):
break
...
def main():
while True:
if keyboard.is_pressed('alt+p'):
start()
This way is stable but it causes a lag, it is hard for me to type something.
def main():
keyboard.add_hotkey('alt+p', start, args=(), suppress=True, trigger_on_release=True)
while True:
# waiting for the user to press hotkey
continue
As I know keyboard.add_hotkey only returns output so I can't stop the loop in the start function.
Is there any better solution?
although this may be late for you, it may help others if they find this...
exit = false
def start():
exit = true
def main():
keyboard.add_hotkey('alt+p', start, suppress=True, trigger_on_release=True)
while not exit:
# put something here, you can't have an empty loop
keyboard.remove_hotkey('alt+p')
When main is called this will add a hotkey that, when triggered, will run the function start. It will then go into the while loop. (note that, unless your are using subprocessing,+ this will stop everything else from going on until you leave the loop) The while loop will run until exit = false. It would probably be a good idea to remove the hotkey, although you may have a reason not too.

Is there any way for console programs to change their execution way, due to some event, like e.g. key press or some event in code?

All programs which I see in tutorials are console and code is executed from first line to the last line and if there is while everything starts from the first line. Is there any way for console programs to change their execution way, due to some event, like e.g. key press or some event in code? The best example of what I want to do is router CLI. Where can I find such examples?
def main():
while(True):
initial_setup() #choose IPs to monitor
while(True):
do_some_work() # do monitor the IPs
I need some listener in the secons while which detects keypresses and then I go to initial setup, meanwhile do_some_work works and only after I finish adittional changes in initial_setup do_some_work restarts.
Sorry I am noob and not very good in explaining probaly because English is not native for me. The best example from real life I can name is CLI of router, you can setup intreface and meanwhile router do routing in the background.
Code for Sergio S:
import threading
import time
def hello():
while(True):
print("Hello")
time.sleep(2)
def hi():
while(True):
print("hi")
time.sleep(2)
def press_key():
a=input()
a=False
return a
def circle():
MrBoolean=True
while(MrBoolean):
thr=[]
thr.append(threading.Thread(target=hello))
thr.append(threading.Thread(target=hi))
thr.append(threading.Thread(target=press_key))
for i in thr:
i.start()
for i in thr:
i.join()
mrBoolean=thr[3]
def main():
while(True):
circle()
main()
From your description, it seems you're searching for something called multithreading: while one part of the application does one thing, the other does something else. See these other questions for more details: How to use threading in Python? , How to stop a looping thread in Python?
whats_typed = input('Say Aah:')
if whats_typed.strip() == 'Aah':
print('Thanks!')
else:
print('Whoops. Your input was:', whats_typed)
The above changes what is executed depending on user input when the program is run.

cleaning up function looping

I am looping a function in python as I created my own constant listener. My question is how can I ensure I don't overflow / crash? Logically this is telling me I am leaving a lot of open functions in the background. Once parameters of my application are met I exit(0) for a clean shut down. but how can I ensure this doesn't eat up memory?
This code works fine btw, but I am simply trying to improve it because it feels really wrong to me that I am calling the function within its self without closing the previous use of it and it just feels dirty. constructive comments please.
e.g. (this is now my actual code)
import serial
import sys
import time
def enterdata():
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r")
time.sleep(0.5)
while True:
data = ser.read(ser.inWaiting())
if (len(data) > 0):
a = []
for i in range(len(data)):
a.append(data[i])
if "Please press Enter to activate this console." in "".join(a):
print ("1")
exit(0)
break
ser.close()
enterdata()
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r\n")
enterdata()
NEW VERSION SO FAR FROM POSTS MADE:
import serial
import sys
import time
def enterdata():
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r")
time.sleep(0.5)
while True:
data = ser.read(ser.inWaiting())
if (len(data) > 0):
a = []
for i in range(len(data)):
a.append(data[i])
if "Please press Enter to activate this console." in "".join(a):
print ('1')
return True
exit(0)
break
ser.close()
ser = serial.Serial(sys.argv[1], sys.argv[2])
ser.write("\r\n")
state = False
while state is not True:
state = enterdata()
This code you showed will give a "RuntimeError: maximum recursion depth exceeded" Error because of Python sets a default value for how many recursions can occur in one function at a time.
Any yours is infinite and definitely will cause problems even if you change this default limit.
Why not make a loop yourself and call the function at will ?
found = False
while not found:
extracted_data = lookfordata()
if extracted_data == "I want it to be equal to this":
found = True
I see you edited the post. Whatever you are trying to do, that method is not efficent, not recommended and not pretty. All the good reasons not to use it.
Imagine that you will handle some data larger than you are using now, you won't know if the recursion stopping condition will come to pass before you exceed the limit. It's also no use to increase limit all the time you encounter a bigger data. I think it should be any programmer's goal to avoid repetition and coming up with programs that can handle any type of unexpected input.
You updated your post again. This way of input handling is much better than raw recursion. Just to mention, instead of;
for i in range(len(data)):
a.append(data[i])
use
for i in data:
a.append(i)

How to have input while a while loop ( or similar) is executed

I do believe that thread may accomplish this, although I am not sure. Most of the threads out there that address this problem doesn't address it to match my problem. I have created a simple mud-like fighting system that executes when you 'fight' an NPC. I have the code that runs under a while loop that checks health between you and NPC and if one of you dies then the loop ends.
However
During the loop I want to have it where a user can type in commands, instead of being stuck watching a looping code block without you being able to do anything. From what I have read online it looks like thread module may be of some help to me? Also if anyone has PyGame experience, maybe looking into that would be a solution? Please let me know what you think.
Below is a very simple example of what I am trying to accomplish.
import time
fighting = True
while fighting:
# do the magic here
time.sleep(4) # to give it a nice even pace between loop intervals
Although at any time i want to be able do input a command like a skill or spell.
Any ideas or suggestions?
You can separate your human interface and fight game into separate threads. The fight game uses a queue for input, which uses a timeout to continue. Here is a very simple queue structure that should minimally do what you want.
import time
import threading
import Queue
def fighter(input_queue):
while True:
start = time.time()
# do stuff
wait = time.time() - start()
if wait <= 0.0:
wait = 0
try:
msg = input_queue.get(wait, wait)
if msg == 'done':
return
# do something else with message
except Queue.Empty:
pass
def main():
input_queue = Queue.Queue()
fight_thread = threading.Thread(target=fighter, args=(input_queue,))
fight_thread.start()
while True:
msg = raw_input('hello ') # py 2.x
input_queue.put(msg)
if msg == 'done':
break
fight_thread.join()
If you only want this to work on Windows, and you want to keep your simple event loop:
fighting = True
inputbuf = ''
while fighting:
# do the magic here
while msvcrt.khbit():
newkey = msvcrt.getwche()
inputbuf += newkey
if newkey == '\r':
process_command(inputbuf)
inputbuf = ''
time.sleep(4) # to give it a nice even pace between loop intervals
On the other hand, if you want to use a background thread, it would be a lot simpler:
def background():
for line in sys.stdin:
process_command(line)
bt = threading.Thread(target=background)
bt.start
fighting = True
while fighting:
# do the magic here
time.sleep(4) # to give it a nice even pace between loop intervals
This works cross-platform, and it gives normal line-buffered input (including full readline support), which people will probably like.
However, I'm assuming you want that process_command to share information with the # do the magic here code, and possibly even to set fighting = False. If you do that without any thread synchronization, it will no longer work cross-platform. (It may work on both Windows CPython and Unix CPython, but will probably not work on IronPython or Jython—or, worse, it will work most of the time but randomly fail just often enough that you have to fix it but not often enough that you can debug it…)
What you may be looking for is a non-blocking raw_input implementation. This would allow the loop to keep going while allowing the user a possibility at entering commands.
There is an example of an implementation of this here and here. Maybe you can adapt one of them to suit your purpose.
Edit:
Or, if you're working on Windows...

Categories