Dynamic Python Countdown Timer - python

Beginner amateur Python scripter here (sorry if I unwittingly use incorrect terms). I'm looking to create a countdown timer in Python that takes into account a set date in the future and the current date.
For example, if I wanted to make a "deathclock" (to wit, a countdown timer that counts down to my estimated date of death) the timer would need to count down from the current date to my estimated date of death years in the future, the latter of which would be hard-coded into the Python script.
I imagine I'd have to do something like get the current date, convert it to seconds, subtract it from the date of death (which would also be converted to seconds), and then convert the difference to a years-months-days-hours-minutes-seconds format, which would then be the starting point of the countdown timer (the timer would preferably need to be able to display years, months, days, hours, minutes, and seconds as it counts down).
Is there a relatively simple way to do this so the timer displays in a Linux terminal, or would doing something like this be a pain?
Thanks in advance for any assistance.

You can get the delta between two times:
from datetime import datetime
my_death = datetime(2044, 3, 24)
lacking = datetime.now() - my_death
This lacking object has some useful attributes you can use, like lacking.days and lacking.total_seconds().

You have to tell the terminal to overwrite the current line instead of printing to a new line.
This will only work on systems that properly handle control characters. It works from a Windows command prompt and I just tested on OSX but doesn't from Idle.
import sys,time
def msg(txt):
sys.stdout.write(txt)
sys.stdout.flush()
for sec in range(10):
time.sleep(1)
m = "%2d seconds" % (10-sec)
msg(m + chr(13))
Regarding the time operations, you can use the datetime module which lets you compute and format date intervals (like +3 days). https://docs.python.org/2/library/datetime.html

Related

A Python infinite loop with arguments that can be manually changed as the script runs

This is my attempt to begin creating a script that runs in "real-time" with parameters that can be changed while the script runs.
My idea is that there will be a Python script that runs as an infinite loop:
output.py
while True:
print(0)
It always outputs 0. There will be a file, right now my guess is a config.ini file (or something similar), where I can set times that the output is 1. Something like:
config.ini
[INPUT]
times = [[4000, 6000], [25000, 55000]]
Note: I am imagining this as a 24hr scale in seconds (86400 seconds), and the intervals are in seconds.
How it works:
I start output.py and it begins running from the current GMT in seconds
I enter my time intervals (i.e. [[4000, 6000], [25000, 55000]]) into config.ini where the output is 1
output.py is consistently "checking" config.ini and importing newly entered time intervals where 0 will be changed to 1, as well as checking if a scheduled time interval was deleted
When the time that has been entered into config.ini occurs (i.e. [4000, 6000]), the output is set to 1 for the duration of the interval that was entered. Once over, the output goes back to 0 and does not become 1 again until another scheduled interval is reached (i.e. [25000, 55000]) .
Additional points:
The config.ini file is consistently being "checked" by output.py for new intervals where the output will be 1 instead of 0. The "checking" would be on the scale of minutes, maybe seconds.
output.py "resets" every time GMT reaches midnight
output.py is working on an actual real life time scale, so output is actually being outputted every second
There could be any number of time intervals entered into config.ini, or none at all
config.ini can be changed at any time while output.py is running
0 and 1 can be thought of as being on the y-axis, and the time intervals being on the x-axis
When output.py resets at midnight GMT, if the time intervals are still in config.ini (i.e. [[4000, 6000], [25000, 55000]]), they will just be applied again at the specified times.
As I mentioned before, it does not need to be a config.ini file, it could be a .txt, or some other type of file, maybe even a database. What I ideally want to use is something that can be modified where entries and deletions can be done manually (I enter and delete time intervals), or automatically (a separate Python script can enter and delete intervals in the config.ini file).
Let me know if clarification is needed. This is a problem I have been trying to figure out for some time, and I would like to have a working example to build off of.
To read INI files, you can use configparser module. Or ConfigParser in Py2.
To pickup new args you set an interval, let say 1 sec or more, and use:
os.path.getmtime("your_file.txt")
if the modification time changed from last time, you reload the arguments.
You may use the Timer() from threading module to activate different actions and a loop that manipulates the timers according to new args.
Or you can make a loop checking different intervals like this:
from time import time, sleep
act_time = time()
check_args = 1.0
while 1:
current_time = time()
if current_time-act_time>=check_args:
reload_args()
act_time = current_time
continue
# And other similar checks according to other vars updated by reload_args() function
sleep(0.001) # Prevent a busy loop
Of course, instead of using time() and resetting
act_time, you can make your own time keeping variable and add 0.001 to it after the sleep(). But you still need a reliable way to check how much time passed for each interval you are checking for and add to them too, so you have to way this things. Nobody will write more code than this for you here. Good luck.

Displaying Raspberry Pi clock on LCD display

I have a Raspberry Pi running an LCD display. I found the Python script below which displays the time on the display, but I notice there's a delay of almost a second between the Pi's time and the LCD.
I tried removing the last line of the code (sleep(1)) and that removed the delay but the LCD flickers a lot.
Can anyone please explain the function of that last line, and whether there's a way to display the time on the LCD without a delay?
Thanks.
#!/usr/bin/python
import RPi.GPIO as GPIO
from Adafruit_CharLCD import Adafruit_CharLCD
from subprocess import *
from time import sleep, strftime
from datetime import datetime
lcd = Adafruit_CharLCD()
lcd.begin(16,1)
GPIO.setup(18, 0)
GPIO.output(18, 1)
while 1:
lcd.clear()
lcd.message(datetime.now().strftime('%b %d %H:%M:%S\n'))
sleep(1)
The sleep(1) instructs the program to "sleep" for 1 second. This is actually very significant because that means that the while loop (which is always true) will then only run once every second. When you take away the sleep(1) line, that means the while loop never takes a break and continues running as fast as the computer can go infinitely. One thing you might try is just reducing the sleep(1) to some smaller value. For example, you can specify sleep(0.1)
By reducing the amount of time it sleeps, that means the clock will update more frequently. Right now with sleep(1) the clock updates once every second, which makes perfect sense. However, you might increase accuracy by having the clock update 10 times every second with sleep(0.1). Let me know if this all makes sense.
The flickering is likely caused by the fact that the program is clearing and repopulating the display so many times a second.
Edit: Documentation suggests that sending decimal values to the sleep() function is valid
Edit 2: An extra bit about how to only refresh the display if right at the turn of a second
from datetime import datetime
from time import sleep, mktime
dti = mktime(datetime.now().timetuple())
while 1:
ndti = mktime(datetime.now().timetuple())
if dti < ndti:
dti = ndti
lcd.clear()
lcd.message(datetime.now().strftime('%b %d %H:%M:%S\n'))
sleep(0.95)
else:
sleep(0.01)
In essence, here's how it works:
When starting the program, create a datetime in integer form (our var dti). By "integer form" I mean add up all the seconds from some arbitrary start date (e.g. 1970-01-01 00:00:00) and use that as a reference for time. For example, today (2016-08-18 00:00:00) might be something like 1471478400 seconds since 1970. Once we have that value, we start our loop.
At the beginning of the loop, we always create a new datetime integer (ndti) to track where we are since the last time we ran the loop. With this information handy, we hop into the if conditional. if our new datetime integer (ndti) has changed fully by one second compared to our old datetime integer (dti) then that means, obviously, one second has passed. Since that is the case, we will now set our reference datetime integer to the datetime now (dti = ndti). Then we display our message (lcd.clear() and lcd.message()). After that we will sleep the program for just under 1 whole second (sleep(0.95)). Since some computers can possibly sleep more than the exact allotted time, this gives us .05 seconds of cushion to be inaccurate. In the event that we are running through the if conditional and a second has not passed yet, we would sleep the program for a short time and continue repeating until a second has actually passed (sleep(0.01)).
If everything goes exactly as planned, then for each second our program should be refreshing the lcd screen only once, and it should also be sleeping for roughly 95% of that second, so that we aren't spinning our wheels for no reason the whole time. Another part to note is that since our else clause tells the program to sleep for 0.01 seconds, that means that, in most cases, our clock can only ever be inaccurate by a margin of 0.01 seconds, which is quite good. This is low enough to be mostly undetectable by humans. Let me know if all this makes sense.
I tested this out via command line (replacing the lcd stuff with simple print statements) and it seemed to line up exactly with another time tracking resource (http://time.is/)
Try it out and see if it works for you.
IT is best way to print date and time on lcd
firstly download or git clone rplcd library for lcd add in upper side of code
import RPLCD
textDate = strftime("%d %A %Y", gmtime())
textTime = strftime("%H:%M:%S", gmtime())
lcd_string(textDate,LCD_LINE_1)
lcd_string(textTime,LCD_LINE_2)

print python counter of GPIO pin output at set intervals

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()

python - how to schedule a function to run at last day of each month?

I want to schedule the function to run at last day of each month using python sched.
can anyone help me for the same?
Run everyday with crontab and check if it is the last day of the month using calendar.monthrange:
import datetime, calendar
today = datetime.date.today()
if calendar.monthrange(today.year, today.month)[1] != today.day:
exit()
Python sched and crontab are not in the same league, unless you are talking about another python sched. Windows has a similar scheduller, or you can install cygwin crontab.
If you are in some weird platform that lacks a system wide task scheduller, you can leave an infinite loop running the above test and time.sleep(24*60*60) seconds or something like that.
Last day of the month has a property that the next date's day value is less than the current one.
Find out how many days are there from the current day to the end of the day. Use the property listed above as the clue. Use datetime module for finding the details.
Write a function def mydaycount(): which starts with 0 for the current day and will yield a higher value for each subsequent day. This is similar to your time.time() call but for each day
Write a function def mydaydelay(num): which will sleep for a day.
Now, the important part here is the
class sched.scheduler(timefunc, delayfunc)
The timefunc can be anyfunction which when called returns a value and in your case, it will be the mydaycount and delayfunc will be mydaydelay.
And then you can call the schduled object with the number of days to the end of the month with action as your action as your function.
scheduler.enterabs(time, priority, action, argument)
A rough outline for your program would be something like this.
import sched
import datetime
def mydaycount():
yield int_days
def mydaydelay(n):
sleep_for_days(n)
scheduler = sched.scheduler(mydaycount, mydaydelay)
def print_event(name):
print 'EVENT:', name
n_days_to_last_day = 3 # This should be your calculate value
scheduler.entertabs(n_days_to_last_day, 1, print_event, ('last day',))
scheduler.run()

How can I repeat something for x minutes in Python?

I have a program (temptrack) where I need to download weather data every x minutes for x amount of hours. I have figured out how to download every x minutes using time.sleep(x*60), but I have no clue how to repeat this process for a certain amount of hours.
UPDATE:
Thank you to everyone who posted a solution.
I marked the example using "datetime.datetime.now() + datetime.timedelta(hours=x)" as the best answer because I could understand it the best and it seems like it will work very well for my purpose.
Compute the time you want to stop doing whatever it is you're doing, and check each time that the time limit hasn't expired. Like this:
finish_time = datetime.datetime.now() + datetime.timedelta(hours=6)
while datetime.datetime.now() < finish_time:
do_something()
sleep_for_a_bit()
I've just found sched in the Python standard library.
You are looking for a scheduler.
Check this thread.
May be a bit of overkill, but for running background tasks, especially if you need a GUI, I'd recommend checking out the PyQt route with QSystemTrayIcon and QTimer
Maybe I'm misunderstanding you, but just put it in a loop that runs a sufficient number of times. For example, to download every 5 minutes for 2 hours you need to download 24 times, so:
for i in range(24):
download()
sleep(5*60)
If you need it to be parameterizable, it's just:
from __future__ import division
from math import ceil
betweenDLs = 5 # minutes
totalTime = 2*60 # minutes
for i in range(int(ceil(totalTime/betweenDLs))):
download()
sleep(betweenDLs*60)

Categories

Resources