self.after doesn't wait when passing value - python

I'm making a gui in python wich uses the serial port for sending commands. In my old script, without a gui, i used time.sleep(x) between the write commands (it is necessary for to commands to succeed). Now when i use a gui envrimont, i can't use sleep so i use after.
It works well, but:
I'm using Tkinter for my gui. When i press the button start , OnButtonClickSTART starts the other function after x time. With self.after i wait x secondes between every process. It works, but when i give a value with the function, it doesn't wait the given time.
def OnButtonClickSTART(self):
print "START"
self.button1.configure(state='disabled')
self.after(1000, self.waitmore)
def waitmore(self):
value = 5
print value
self.after(10000,self.waitmuchmore(value))
def waitmuchmore(self,value):
print value
self.after(10000,self.OnButtonClickSTOP)
def OnButtonClickSTOP(self):
print "STOP"
self.button1.configure(state='normal')
And isn't here a better way to execute a series of command , with a certain time between them. Like sleep, but works with 1 function and doesn't disable the gui.
Thx

Using self.waitmuchmore(value) will immediately call the waitmuchmore method. You need to use either a lambda expression or functools.partial to return a new function that will call waitmuchmore with value, and pass that to self.after instead:
lambda: self.waitmuchmore(value)
or
import functools
functools.partial(self.waitmuchmore, value)

Related

Using the same hotkey for two different purposes in Python

Using pythons keyboard library,
I have two function definitions:
def start_tracking():
*code to start tracking time*
def end_tracking():
*code to stop tracking time*
I then want to use the same hotkey (e.g. F1) to invoke function 1 (start tracking time) on the first press and then function 2 (end tracking time) on the subsequent press. If I press the hotkey again after that, it should repeat the process.
Basically I want to use the same hotkey to track time and stop tracking time.
Here's what a working solution to start tracking time and stop tracking time using two different hotkeys looks like:
keyboard.add_hotkey("F1", start_tracking)
keyboard.add_hotkey("F2", end_tracking)
How can I accomplish the same thing with only one key (F1)?
I don't want to use a while loop because it slows down performance quite a bit.
Consider using a class variable or global variable as a flag. Such that:
class tracker():
def __init__(self):
self.start_flag = True <- Init class variable
def tracking(self):
if self.start_flag:
start_tracking()
self.start_flag = False #<- class variable toggling
else:
stop_tracking()
self.start_flag = True #<- class variable toggling
if name == '__main__'
x = tracker()
x.tracking() # starts tracker
time.sleep(5)
x.tracking() # stops tracker
Without more context on what your program is doing I can't say which is better. Typically globals should be avoided though. Simply put, you need a way to toggle which function is run. PS copypasting wont work. You will need to setup the class etc for proper usage. especially with where and how you defined start/stop. I would guess you are using globals but typically this should be avoided.
Solution:
def started():
start_tracking()
keyboard.remove_hotkey("F1")
keyboard.add_hotkey("F1", ended)
def ended():
end_tracking()
keyboard.remove_hotkey("F1")
keyboard.add_hotkey("F1", started)
#Hotkey
keyboard.add_hotkey("F1", started)
Basically I switch between the two events every time I press the hotkey by calling two functions in an alternating fashion.

Only run function it is not already running

I need to make on auto clicker that, when the mouse is clicked once (using the 'mouse' module), presses another 5 times. However, I also need to make sure that only the clicks done by the user activate it. Currently (because I don't need an unstoppable mouse as I've already had), it only prints "clicking". This is what I have so far.
jack = 0
import keyboard
import mouse
import sys
from time import sleep
def spamClick(f, jeff):
if jeff <= 0:
jeff = jeff+1
for i in range(f):
#mouse.click()
print ("Clicking")
sleep(0.1)
jeff = 0
mouse.on_click(spamClick, args=(5, jack))
#keyboard.add_hotkey('ctrl+g', spamClick)
keyboard.add_hotkey('ctrl+#', mouse.unhook_all)
keyboard.add_hotkey('ctrl+#', sys.exit)
Thank you in advance.
An easy fix for this is having a top level variable keeping track of the state.
The issue is that you have a function that does an action that starts itself again.
It's functionally the same as
def examplecode():
print("Do stuff")
examplecode()
This is the same as an infinite loop, in your case even worse because you call the function multiple times every time (5 times per action).
So your options to prevent that are as follows:
Have two different ways of clicks, one that triggers the "onclick" event, and one that doesn't.
Use a helper function that keeps track of the "state" of your program. Instead of calling "spamClick()" as your onclick event add the following to your program:
A top level variable that is True when you want it to accept clicks: isUser=True
A function you call instead of "spamclick" that checks the state of the global Var and only then triggers the code:
def examplefunc(num,var):
if isUser:
isUser=False
spamClick(num,var)
isUser=True
I still don't get how your program just "clicks endlessly" instead of crashing due to hitting max recursion depth, but this should work (while being very hacky)
Edit: You should use better naming for variables instead of "jeff", it will make your life worse if you don't down the line. For example "isUser" indicates that it's a boolean (because "isWhatever" indicates it holds a state as a boolean) and states if the input is by a user. Alternatively you could use isFunctionRunning=False that states if the function is on. You would have to switch all the True and False assignments in my example of course to still make sense.

In python curses, how i can get string from user and print on the screen in same time

I used the curses library in Python to divide the screen into two part, the first half to print a set of strings and the second half to get the user input by using getstr() , but when the user enters the ipnut curses interrupt the entry and clear the user's entries
def main(stdscr):
curses.curs_set(0)
stdscr.nodelay(1)
stdscr.timeout(100)
i = 0
while 1 :
i = i+1
stdscr.addstr(0,0,"frame"+str(i))
curses.echo()
user_input = stdscr.getstr(5,0)
stdscr.addstr(7,0,user_input)
curses.wrapper(main)
getstr won't help with this. If you want to concurrently update the screen and get input, you'll have to make a function like getstr, using getch, and allowing the getch calls to time-out (to do the addstr calls periodically).
The nodelay function can help with this, though using that tends to use too much processing time. It's usually preferable to use timeout, e.g., 10-20 milliseconds.

How to keep a While True loop running with raw_input() if inputs are seldom?

I'm currently working on a project where I need to send data via Serial persistently but need to occasionally change that data based in new inputs. My issue is that my current loop only functions exactly when a new input is offered by raw_input(). Nothing runs again until another raw_input() is received.
My current (very slimmed down) loop looks like this:
while True:
foo = raw_input()
print(foo)
I would like for the latest values to be printed (or passed to another function) constantly regardless of how often changes occur.
Any help is appreciated.
The select (or in Python 3.4+, selectors) module can allow you to solve this without threading, while still performing periodic updates.
Basically, you just write the normal loop but use select to determine if new input is available, and if so, grab it:
import select
while True:
# Polls for availability of data on stdin without blocking
if select.select((sys.stdin,), (), (), 0)[0]:
foo = raw_input()
print(foo)
As written, this would print far more than you probably want; you could either time.sleep after each print, or change the timeout argument to select.select to something other than 0; if you make it 1 for instance, then you'll update immediately when new data is available, otherwise, you'll wait a second before giving up and printing the old data again.
How will you type in your data at the same time while data is being printed?
However, you can use multithreading if you make sure your source of data doesn't interfere with your output of data.
import thread
def give_output():
while True:
pass # output stuff here
def get_input():
while True:
pass # get input here
thread.start_new_thread(give_output, ())
thread.start_new_thread(get_input, ())
Your source of data could be another program. You could connect them using a file or a socket.

Return continuous result from a single function call

I have got stuck with a problem.
It goes like this,
A function returns a single result normally. What I want is it to return continuous streams of result for a certain time frame(optional).
Is it feasible for a function to repeatedly return results for a single function call?
While browsing through the net I did come across gevent and threading. Will it work if so any heads up how to solve it?
I just need to call the function carry out the work and return results immediately after every task is completed.
Why you need this is not specified in the question, so it is hard to know what you need, but I will give you a general idea, and code too.
You could return in that way: return var1, var2, var3 (but that's not what you need I think)
You have multiple options: either blocking or non-blocking. Blocking means your code will no longer execute while you are calling the function. Non-blocking means that it will run in parallel. You should also know that you will definitely need to modify the code calling that function.
That's if you want it in a thread (non-blocking):
def your_function(callback):
# This is a function defined inside of it, just for convenience, it can be any function.
def what_it_is_doing(callback):
import time
total = 0
while True:
time.sleep(1)
total += 1
# Here it is a callback function, but if you are using a
# GUI application (not only) for example (wx, Qt, GTK, ...) they usually have
# events/signals, you should be using this system.
callback(time_spent=total)
import thread
thread.start_new_thread(what_it_is_doing, tuple(callback))
# The way you would use it:
def what_I_want_to_do_with_each_bit_of_result(time_spent):
print "Time is:", time_spent
your_function(what_I_want_to_do_with_each_bit_of_result)
# Continue your code normally
The other option (blocking) involves a special kind of functions generators which are technically treated as iterators. So you define it as a function and acts as an iterator. That's an example, using the same dummy function than the other one:
def my_generator():
import time
total = 0
while True:
time.sleep(1)
total += 1
yield total
# And here's how you use it:
# You need it to be in a loop !!
for time_spent in my_generator():
print "Time spent is:", time_spent
# Or, you could use it that way, and call .next() manually:
my_gen = my_generator()
# When you need something from it:
time_spent = my_gen.next()
Note that in the second example, the code would make no sense because it is not really called at 1 second intervals, because there's the other code running each time it yields something or .next is called, and that may take time. But I hope you got the point.
Again, it depends on what you are doing, if the app you are using has an "event" framework or similar you would need to use that, if you need it blocking/non-blocking, if time is important, how your calling code should manipulate the result...
Your gevent and threading are on the right track, because a function does what it is programmed to do, either accepting 1 var at a time or taking a set and returning either a set or a var. The function has to be called to return either result, and the continuous stream of processing is probably taking place already or else you are asking about a loop over a kernel pointer or something similar, which you are not, so ...
So, your calling code which encapsulates your function is important, the function, any function, eg, even a true/false boolean function only executes until it is done with its vars, so there muse be a calling function which listens indefinitely in your case. If it doesn't exist you should write one ;)
Calling code which encapsulates is certainly very important.
Folks aren't going to have enough info to help much, except in the super generic sense that we can tell you that you are or should be within in some framework's event loop, or other code's loop of some form already- and that is what you want to be listening to/ preparing data for.
I like "functional programming's," "map function," for this sort of thing. I think. I can't comment at my rep level or I would restrict my speculation to that. :)
To get a better answer from another person post some example code and reveal your API if possible.

Categories

Resources