For example, I have this function:
some_global_varible = ""
def bob(some_argument, some_more):
import time
for x in range(10):
print("Working")
time.sleep(1)
return "I finished and this is my result"
How can I run this function for certain amount of time, and if it's not finish in the time end it. But also if it finish get the output of the return (if the is one, because maybe there is none and it simply end).
Also this won't be run in Unix, because I had see some example for Unix that don't work in Windows. Also if you could change the global variable form inside the function it would be perfect, but that as a extra.
First the rest and if it possible (If it not possible to detect an end without the return it doesn't matter, I can include a return just fro that. Like: return "This is just for ending")
EDIT:
The "bob" funtion is an example for a function that takes 10 seconds, but the plan is to use it on other functions, that can take an undefined amount of time. And that function can't be edited to add simply something to stop it at some time seconds.
A better example could be "pep" as it wouldn't end by itself.
def pep():
import time
while True:
print("Working")
time.sleep(1)
You can use time.time() to get the current time in seconds before you start your loop and then at the end of each for loop, check how long has passed since then and if it's too long then you can return.
def bob(some_argument, some_more):
import time
start = time.time()
for x in range(10):
print("Working")
time.sleep(1)
if time.time() - start > 5:
return "I took too long"
return "I finished and this is my result"
Obviously replace 5 with the time you want to use, but this code gives me this output:
Working
Working
Working
Working
Working
'I took too long'
You may use the break;
For example if the value of the loop counter meets a following condition like this:
if condition:
break;
this will surely end the loop.
Related
I need to download some files weekly at a time and day specified by the user as shown in the screenshot.
I am struggling with integrating an inner loop with respect to root.mainloop().
So far I have tried with .after and with a while structured like this:
def scaricaAuto(myDay, myHour, myMinute):
while True:
day = datetime.datetime.now().strftime("%A")
hour = datetime.datetime.now().strftime("%H")
minute = datetime.datetime.now().strftime("%M")
if day == myDay and str(int(hour)) == myHour and str(int(minute)) == myMinute:
DownloadButton.invoke()
break
root.after(60000, scaricaAuto(clickedDays.get(), HourSpin.get(), MinSpin.get()))
Using only .after leads to Python: maximum recursion depth exceeded while calling a Python object and the while loop doesn't behave properly, when the if is true it gets stucked there and keeps invoking DownloadButton.
Also OS X shows my script to be "not responding" when a button function last longer than a few seconds, is there a solution for this to?
Thanks in advance to those that took the time to read my question and might be able to help me!
There are a couple of problems in your code. First, you need to remove while True. That serves no purpose. Tkinter is already running an infinite loop by way of mainloop.
Second, after requires a function. You're calling a function and passing the result to after.
In other words, this:
root.after(60000, scaricaAuto(clickedDays.get(), HourSpin.get(), MinSpin.get()))
... is functionally identical to this:
result = scaricaAuto(clicedDays.get(), HourSpin.get(), MinSpin.get())
root.after(60000, result)
Instead, you either need to pass scaricaAuto as an argument, or you need to create a new function that calls your function. In the case of the former, you can pass arguments to the function by passing those arguments to after.
For example,
root.after(60000, scaricaAuto, clickedDays.get(), HourSpin.get(), MinSpin.get())
Note that this calls the .get() functions immediately rather than waiting the full 60 seconds.
A better solution is to not pass any arguments to scaricaAuto and instead have it call the .get() methods right when it needs the values:
def scaricaAuto():
myDay = clickedDays.get()
myHour = HourSpin.get()
myMinute = MinSpin.get()
now = datetime.datetime.now()
day = now.strftime("%A")
hour = now.strftime("%H")
minute = now.strftime("%M")
if day == myDay and str(int(hour)) == myHour and str(int(minute)) == myMinute:
DownloadButton.invoke()
root.after(60000, scaricaAuto)
The above code will run for as long as the GUI itself is running, assuming you've called mainloop at some point.
this is the first time I am reaching out with a question so hopefully I get the format right.
I am trying to limit the running time of my function (lets call it 'recursive_tsp_function') that is called from inside another function. This function recursive_tsp_function sometimes (not always) for unknown reasons keeps running infinitely.
CONTEXT:
Already, I tried implementing some sort of time checks like this
def recursive_tsp_function(parameters)
start = time.time()
... (function here)
now = time.time()
if (now - start) > max_time:
return
... (function continues)
But for some reason my kernel in debugging mode keeps running the recursive function infinitely until I manually pauze the running and go on step by step in the debugger and than it does register the time checks and than stops the function like it should.
NOW:
Because that approach didn't work I looked a better method online and came upon working with threads. I now have the following method based an a simple online example:
'Countdown' is my timer function (in the same file as the 'above_function').
The structure of my function above 'above_function' you can see below (note that it threads the timer).
Also I added a 'check' function to the same file as the above_function that checks whether the timer has run out. I did this because there was a problem with referring to the global variable my_timer from the recursive_tsp_function which is located in a different file (I would think my_timer being a global variable would make it accessible from other functions but anyway that seems to be resolved for now)
def countdown(max_time_timer):
global my_timer
my_timer = max_time_timer
for x in range(max_time_timer):
my_timer = my_timer - 1
time.sleep(1)`
def check():
global my_timer
if my_timer ==0:
return False
else: return True
def above_function(...):
...
countdown_thread = threading.Thread(target = countdown(10))
countdown_thread.start()
route = recursive_tsp_function(parameters)
...
return route
And than in a different file I have the recursive_tsp_function that would look something like this where I routinely run the check function from above and check whether my_timer is 0 yet:
def recursive_tsp_function(variables):
...
if not check():
return
...
return recursive_tsp_function(variables)
The PROBLEM that I have with this setup is there seems to be no threading taking place, the timer first runs out and only than the function recursive_tsp_function would run. Naturally this function stops immediately because the timer is already on 0.
Thank you for being patient with my long explanation. If anybody got tips on how to tackle a timer on a function like this I would be very grateful.
you should create the thread like this.
# target is the callable object
# args is the argument tuple for the target invocation
countdown_thread = threading.Thread(target = countdown, args=(10,))
What if you try
maxtime = int(input("What is the time for the timer?"))
import time
time_went = 0
for i in maxtime:
time_went = i
time.sleep(1)
And then instead of using time_went == 0 you can use time_went == maxtime?
Is there an easy way to execute time delay (like time.sleep(3)) between every statement of Python code without having to explicitly write between every statement?
Like in the below Python Script which performs certain action on SAP GUI window. Sometimes, the script continues to the next statement before the previous statement is complete. So, I had to add a time delay between every statement so that it executes correctly. It is working with time delay, but I end up adding time.sleep(3) between every line. Just wondering if there is a better way?
import win32com.client
import time
sapgui = win32com.client.GetObject("SAPGUI").GetScriptingEngine
session = sapgui.FindById("ses[0]")
def add_record(employee_num, start_date, comp_code):
try:
time.sleep(3)
session.findById("wnd[0]/tbar[0]/okcd").text = "/npa40"
time.sleep(3)
session.findById("wnd[0]").sendVKey(0)
time.sleep(3)
session.findById("wnd[0]/usr/ctxtRP50G-PERNR").text = employee_num
time.sleep(3)
session.findById("wnd[0]").sendVKey(0)
time.sleep(3)
session.findById("wnd[0]/usr/ctxtRP50G-EINDA").text = start_date
time.sleep(3)
session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT/ctxtRP50G-WERKS[1,0]").text = comp_code
time.sleep(3)
session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT/ctxtRP50G-PERSG[2,0]").text = "1"
time.sleep(3)
session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT/ctxtRP50G-PERSK[3,0]").text = "U1"
time.sleep(3)
session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT").getAbsoluteRow(0).selected = True
time.sleep(3)
return "Pass"
except:
return "failed"
The right way to do what you asked for is almost certainly to use the debugger, pdb.
The right way to do what you want is probably something completely different: find some signal that tells you that the step is done, and wait for that signal. With problems like this, almost any time you pick will be way, way too long 99% of the time, but still too short 1% of the time. That signal may be joining a thread, or waiting on a (threading or multiprocessing) Condition, or getting from a queue, or awaiting a coroutine or future, or setting the sync flag on an AppleEvent, or… It really depends on what you're doing.
But if you really want to do this, you can use settrace:
def sleeper(frame, event, arg):
if event == 'line':
time.sleep(2)
return sleeper
sys.settrace(sleeper)
One small problem is that the notion of line used by the interpreter may well not be what you want. Briefly, a 'line' trace event is triggered whenever the ceval loop jumps to a different lnotab entry (see lnotab_notes.txt in the source to understand what that means—and you'll probably need at least a passing understanding of how bytecode is interpreted, at least from reading over the dis docs, to understand that). So, for example, a multiline expression is a single line; the line of a with statement may appear twice, etc.1
And there's probably an even bigger problem.
Sometimes, the script continues to next step before the previous step is fully complete.
I don't know what those steps are, but if you put the whole thread to sleep for 2 seconds, there's a good chance the step you're waiting for won't make any progress, because the thread is asleep. (For example, you're not looping through any async or GUI event loops, because you're doing nothing at all.) If so, then after 2 seconds, it'll still be just as incomplete as it was before, and you'll have wasted 2 seconds for nothing.
1. If your notion of "line" is closer to what's described in the reference docs on lexing and parsing Python, you could create an import hook that walks the AST and adds an expression statement with a Call to time.sleep(2) after each list element in each body with a module, definition, or compound statement (and then compiles and execs the result as usual).
Anything you want to happen in a program has to be explicitly stated - this is the nature of programming. This is like asking if you can print hello world without calling print("hello world").
I think the best advice to give you here is: don't think in terms of "lines", but think in term of functions.
use debugging mode and watch each and every line executing line by line.
I'm using Python 2.7 and want to use the datetime functions to calculate a user defined time to run a small pump. I know I'm missing something obvious but I've searched until I can't see straight. I have a textCtrl that the user will enter the minutes he wants the pump to run. Then a button click will start the scheduler and check to see if it's time to turn off the pump:
def timedPump(val):
now = datetime.datetime.now()
timeOff = now + datetime.timedelta(minutes=int(val))
if timeOff > now:
print 'pumpOn'
else:
print 'pumpOff'
return True
The problem is that datetime.datetime.now() updates everytime. How do I make it so that now = the time that the button was clicked?
This would be my solution to the problem:
from time import sleep
def pumpcheck(timer_in_minutes):
time_clicked = datetime.datetime.now()
now = time_clicked
timeDiff = datetime.timedelta(minutes=int(timer_in_minutes))
while (time_clicked + timeDiff > now):
print 'pumpOn'
now = datetime.datetime.now()
sleep(2)
print 'pumpOff'
It saves the time when the button was pushed and then checks in a loop, if the time is rfeached, if not, it update the current time, says pump is still on and sleep for a little while to not bloack cpu recources. When the time is reached, it says pumpoff
There is some information missing as to how timedPump is evaluated. I guess it's a simple loop.
What needs to happen is there have to be two functions, one that sets a turnOff-time and one that evaluates weather to turn on / off the pump.
This can be implemented as two methods of a class:
class PumpControl(object):
def setTime(self, val):
now = datetime.now()
self.timeOff=now + timedelta(minutes=int(val))
print 'pumpOn'
def checkTime(self):
if self.timeOff < datetime.now():
print 'pumpOff'
This way you would create a PumpControl object and then repeat checkTime:
controller = PumpControl()
#inside your loop
controller.checkTime()
#when you want to set the time
controller.setTime(val)
This should work across threads as well, so you can have one thread repeating and another asking for the time.
This sounds like something outside the scope of a single function. Either split the logic into two functions, or use a class to preserve start_time
I'm having a problem with a task i'm doing with an anemometer that works using a switch every revolution. The task is using a raspberry pi therefore the language is in python.
What I am trying to do is print a counter value every 10 seconds. However I don't want it to be a delay where nothing happens during the 10 second wait. Basically I want the number of times a switch is pressed in 10 seconds printed to me every 10 seconds.
Sorry if that was vague any extra info needed just ask.
While True:
stuff = dio.readU8(portB)
dio.write8(portA, stuff)
if stuff == 192:
print ('on')
else:
print ('off')
This is what it currently does simply constantly print its state either on or off I havn't yet implemented a counter as I am unsure the way it works in python and am wondering if it is similar to other languages i'm new to python I only usually use Java. The above code works even though values may look weird.
You could use the time module to watch the time, put it in at the end of the event catching code to see if 10+ seconds has passed.
something like...
import time
last_time = time.time()
#start of event catching loop
if time.time() - last_time >= 10
print buttonCountVariable
last_time = time.time()