Python: get next item from a list on a schedule - python

This is my first posted question; I am a new coder who is trying to make a fun quiz app for a friend using Flask, Jinja, and Python. In the quiz, you get 6 different clues each day that point you towards a specific answer (not multiple choice, a specific answer). I have a list with all the answers, and I am currently trying to get the next item in the list...but the problem that I'm running into is that I want this to happen on a schedule, every 24 hours. That's the hard part: I can print the next item in the list just fine, but I can't figure out how to then automatically print the next item at a specific time interval. Once I have that I think I'll be well on my way! (I really want to do this in Python, not JavaScript, because I know even less JavaScript than I do Python).
Here's several things I've tried:
import schedule
from schedule import every, repeat
import time
answers = ["answer1", "answer2", "answer3"]
#repeat(every(3).seconds)
def fetch():
global answers
answers += 0
print(answers)
while 1:
schedule.run_pending()
time.sleep(1)
This returns the error: 'int' object is not iterable.
I have also tried:
import schedule
import time
def job():
answers = ["answer1", "answer2", "answer3"]
for answer in answers:
print(answer[0:])
schedule.every(10).seconds.do(job)
while 1:
schedule.run_pending()
time.sleep(1)
This just prints all the books at once; not what I want, I want a different one every interval (here 10 seconds, but in reality 24 hours).
Another thing I tried:
import schedule
import time
def job():
answers = ["answer1", "answer2", "answer3"]
answersIterator = iter(answers)
print(next(answersIterator))
schedule.every(10).seconds.do(job)
while 1:
schedule.run_pending()
time.sleep(1)
This just prints the first item from the list on repeat; I want it to go through the list, but not all at once, at a specific interval.
I have read through as many tutorials as I can get my hands, but because I'm new at this I'm struggling. Apologies if there are formatting issues here; I read through the guidance before posting, but first time, etc. etc. Thanks all!

Consider where you define variables and in which area they are valid. In the last attempts, for this reason, the iterators do not maintain their state. They are recreated each time the function is called and disappear again when the function is exited.
The following example defines a global iterator that starts over at the end of the sequence. Its state is preserved because it was not defined in the local scope of the function. Within your repeatedly called function you can now query the next element at regular intervals with next(iterator).
from itertools import cycle
from schedule import every, repeat, run_pending
import time
iter_answers = cycle(["answer1", "answer2", "answer3"])
#repeat(every(10).seconds)
def job():
print(next(iter_answers))
while True:
run_pending()
time.sleep(1)
However, I don't understand how you want to use the code inside Flask.
If I understood you correctly, the client should ask for an answer, which is updated and provided by the server at intervals. So you should think about how to write an endpoint that matches a timestamp and depending on that uses the next element in the sequence. So possibly something like this.
from flask import Flask
from datetime import datetime
class Provider:
def __init__(self, items):
self._i = 0
self._t = datetime.now()
self.items = items
def next(self):
if (datetime.now() - self._t).total_seconds() >= 10:
self._i = (self._i + 1) % len(self.items)
self._t = datetime.now()
return self.items[self._i]
provider = Provider([
'answer1',
'answer2',
'answer3',
])
app = Flask(__name__)
#app.route('/')
def index():
return provider.next()

Related

Function that substracts a certain number every second on Python

I have been wondering if there is a way to create a function that subtracts one number from another but only at a given amount of time. I have read the time library, but I am still trying to figure it out. For example:
def TimeFunction:
t = 60
#What should I need to put here so for every second that passes, it subtracts 1?
This is what you are literally asking for:
import time
def TimeFunction():
t = 60
while True:
time.sleep(1)
t -= 1
Although this is not very satisfying, because your program blocks on sleep() and nothing else would be able to see the value of t.
Do you want to modify your question now and ask for something slightly different?

How to create a non cumulative version of sleep() in Python

Please, accept my apologies for the delayed feedback. It was impossible before.
I'll explain it better.
I've built a Midi - OSC control surface for Reaper in Python. It receives and sends OSC messages.
I use UP and DOWN arrows on the keyboard to move through tracks in Reaper. I can move very fast through tracks until I find the one I want to stay on. Then, my script sends a OSC message to receive everything from Reaper using PythonOSC.
I will explain using code.
That function receives OSC messages (e.g.: /track/volume, etc.) Each time the client receives /select, it tells my script that a track changed in Reaper.
def OSC(self, *args):
s = re.search(r'/track/(.+)', args[0])
if s:
if s.group(1) == 'select' and args[1] == 0:
"""I want that next line to be executed only when about 0.5 second had passed
since the last time it enters that point. It is to avoid that PythonOSC sends
that line 10 times in 1 second and overloads the process."""
client.send_message('/device/track/follows/last_touched', 1)
I imagined something like that but I don't know if it's overkill, if I miss something.
Each time I press up or down, a timer starts in a thread or something. It resets each time.
When I land on my track, the timer continues until 0.5 second and then, launches my client.send_message() line.
Is it too much? The thing is, a thread will still have to be killed or something. I'm very new to Python.
The example given, with the decorator is great but it activates the function (in my case, it's finally only a line of code) when it's triggred within 0.5 second while I want it to be triggered after a 0.5 second pause following the last time it's called.
Note: I realize that my code example is all sent in a block in the preview box. I indented it but it breaks it. I'm very sorry for that, I can't see the option I need to use.
I'm not sure that I've interpreted your question correctly, but if you're trying to make function execution to take not less than provided time, you can use this decorator
from time import time, sleep
def timed(time_to_sleep):
def decorator(function):
def wrapper(*args, **kwargs):
start_time = time()
result = function(*args, **kwargs)
time_to_sleep_left = time_to_sleep - (time() - start_time)
if time_to_sleep_left > 0:
sleep(time_to_sleep_left)
return result
return wrapper
return decorator
Usage:
#timed(0.5)
def test():
pass

How can you update local time from the datetime module?

I am writing a program that uses a while loop to check if it is a certain time, and if it is that certain time, it prints a statement. I have all the if-statements set up, but the time does not update once the program starts (if I start the program at 6 pm, it will always output 6 pm for local time). Is there a way to update the time within the while loop?
I tried to research some additional functions/methods to datetime, but from what I have seen, I have not been able to find any that updates the time while the program is running. Additionally, forums regarding datetime and locale time that I have found on stackoverflow are commonly ones that just explain how to obtain the locale time once (ex, Python datetime module current time in HR:MIN:SEC). Other forums regarding locale times that I have found also tended to be in different languages, particularly C# and PHP. Please correct me if there is another forum that answers my question!
from datetime import date
from datetime import time
from datetime import datetime
import time
import webbrowser
now = datetime.now()
sleep = False
today = date.today()
roundCheck = 0
print("Awaiting time check...")
while sleep != True:
print('Up here...')
if roundCheck != 0:
print('Stuck in time...')
time.sleep(60)
print('Time is done')
if str(now.strftime('%H')) == '20' and str(now.strftime('%M')) == '05':
print('Now the while loop will end')
sleep = True
roundCheck = 1
print('Another round has passed')
print('Outside while loop')
When the time is 20:05, sleep should be set to true and the print statement outside the while loop can be executed. However, when I start the program at an earlier time (20:00, for example), it only uses that time for checking now.strftime().
now never changes. You simply need to put now = datetime.now() in the while loop.

How to cancel a request after 5 minutes without a reply

I have the following function,
import requests
def get_url_type(data):
x = {}
for i in range(0,len(data)):
print i
try:
x[i] = requests.head(data['url'][i]).headers.get('content-type')
except:
x[i] = 'Not Available'
return(x)
This function returns the URL type of each URL that is being passed to it and whenever there is no response, it throws error which is caught using exception. My problem here is, some of the requests take more than 5-10 mins time which is too much on production environment. I want the function to return "Not Available" when it takes more than 5 mins. When I did a research about it, it was mentioned to convert the function to asynchronous one. I have trying to change it without much success.
The following is what I have tried,
import asyncio
import time
from datetime import datetime
async def custom_sleep():
print('SLEEP', datetime.now())
time.sleep(5)
My objective is, whenever the request function takes more than 5 mins, it should return "Not available" and move to the next iteration.
Can anybody help me in doing this?
Thanks in advance !
It seems you just want a request to time out after a given time has passed without reply and move on to the next request. For this functionality there is a timeout parameter you can add to your request. The documentation on this: http://docs.python-requests.org/en/master/user/quickstart/#timeouts.
With a 300 seconds (5 minutes) timeout your code becomes:
requests.head(data['url'][i], timeout=300)
The asynchronous functionality you are mentioning has actually a different objective. It would allow your code to not have to wait the 5 minutes at all before continuing execution but I believe that would be a different question.

Python: threading.timer not respecting the interval

This is a followup to another question, to which I now have a solution but the implementation doesn't seem to be behaving properly for unrelated reasons.
I have the following code:
import time
import datetime
import threading
def scheduled_function(cycle):
cycle += 1
print "Cycle " + str(cycle) + " complete."
print "Next cycle at " + (datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime("%l:%M%p")
threading.Timer(300, scheduled_function(cycle)).start() # New cycle every 5 mins
return
scheduled_function(1)
while(True):
command = raw_input()
print command
In general this seems to accomplish what I want - allowing the user to enter commands while in the background while a function is periodically called to do some sort of regular activity. However, the interval (300 in this case, which should equate to 5 minutes) does not seem to be doing anything, and the program reaches maximum recursion depth within a second or so. (Max recursion is not a problem for the actual script, as it likely won't be run for more than a few hours at a time).
How am I using threading.Timer wrongly?
That's because you are calling it right away and not letting the Timer call it for you.
threading.Timer(300, scheduled_function, args=[cycle,]).start()

Categories