How to make Tkinter python script take variable every X seconds? - python

First of excused my poor coding skills. Just started learning about a week ago
Anyway, I'm trying to right now create a GUI for this weather/clock thing for a project. Right now I need it so that the GUI, I was thinking of using Tkinter, updates every second and basically pulled strings from this program. Currently, the program calculates the time of sunrise and sunset and lunar cycle.
I tried two ways so far, the first method, running the entire program under one script, but it doesn't work due to the mainloop() prevent the calculation from repeating itself for the next day.
So now I was hoping to separate the program into two parts. One with the calculations and the other as the main GUI program. So what I did was basically.
Simplified Calculation Script (Its very long so I write the important part):
its day.py
import datetime
import math
import schedule
import astral
a = Astral()
def tick():
d = datetime.datetimee.today()
second = d.second
minutes = d.minute
hour = d.hour
month = d.month
print(str(hour) + ":" + str(minute) + ":" + str(second))
def mooninfo():
global percent_illuminate
global moon_phase
moon_phase = a.moon_phase(date=datetime.date(year,month,day)
percent_illuminate = VERY LONG EQUATIONS
print("Moon is at... " + str(moon_phase))
print(percent_illuminate)
schedule.every(1).second.do(tick)
schedule.every().day.do(mooninfo)
while True:
schedule.run_pending()
And for the tkinter script I tried
from day import moon_phase
Instead of just importing the moon_phase it started to run the program printing out the time of day nonstop.
So if anyone could help me
Let the tkinter script update everytime the different variable, second, minutes, hour, day, month, and moon_phase changed.
Or is there a way to get around the mainloop() of tkinter and just make it run while True: loop too?
Or any other better way to do it.
I saw that you can let Tkinter track the time making a digital clock of the sort but I need the calculations and also I am also sending variables over to an Arduino too (But I already figured that out).
Any help is greatly appreciated, thanks

You're importing a variable from a function. I think you should be importing the class (restructure day.py as a class first), then calling the mooninfo() method to return the value of the moon_phase variable.

Related

How to log the precise time when GUI got updated?

I am developing an application for an experiment using Kivy library in Python. How can I log the precise time (with less than a second precision) when the GUI gets updated - some label changes or text appears?
It seems like the simple logging with the timestamp gives me very unprecise timing. Besides, I am using Clock.schedule_once to delay a GUI label update. That creates even more discrepancies between the log timestamps and the actual timing of things appearing on the screen.
Example of the code:
event = Clock.schedule_interval(self.doThing, 2)
logging.info('the thing is done')
well, unfortunately I don't quite understand what you want.
but if I got it right, you want to know how long it takes for your GUI to be updated?
I have an example that may be useful to you.
import time
start_count = time.time()
#Your script (put the part that does the gui update inside these two lines of code)
print(f"Finish in: {round(1000 * (time.time() - start_count))} ms ")
this will show you exactly how long it takes to execute everything between these two codes
ex:
import time
from PIL import Image, ImageGrab
start_count = time.time() #start count
px = ImageGrab.grab().load() # this will take a screenshot
print(f"Finish in: {round(1000 * (time.time() - start_count))} ms ") # how much he takes to finish
# if you want see how much he takes in seconds, you just need delete "1000 * "
Output:
Finish in: 38 ms

Prevent keystrokes

It is necessary to make sure that during a certain period of time they are not available for pressing a certain key, for example Space. So that during a break, user clicks are not displayed in any way in the input(). Please suggest a module or a complete solution. Example:
import time
time.sleep(5) # So that during this period of time nothing could be written.
enter = input()
welcome to SO!
Your description is very vague, but assuming you want to prevent a specific keystroke from affecting your program for 5 seconds, this might just work:
import keyboard
import time
time_end = time.time() + 5
while time.time() < time_end:
if keyboard.is_pressed('q'):
pass
replace 'q' with the key you don't want to affect your program. Wherever "pass" is is what will happen if q is pressed within those seconds. I think q will still show up in your program when it's pressed, but wont affect any of your other functions unless you have threading. Sorry if this doesn't help, this is the only thing I could think of.

How to use a function when the current time equals another time: Python

I am developing a script that utilizes a function I made to control the relays of an 8 channel relay board on a Raspberry Pi 3. The function works, and calling the function works. I am trying to develop this script so when the current time equals another time, such as Zone 1 start time, the relays turn on/off depending on the status that is received by another part in the code.
I have tested it without this time equals part, and everything works. I seem to be running into some problems when I add this level of complexity. Here is a sample of my code:
while True:
from datetime import datetime
import time
import smbus
ValveStatus='00000001' #0 is closed, 1 is open.
R1_1,R2_1,R3_1,R4_1,R5_1,R6_1,R7_1,R8_1=list(map(int, ValveStatus))
currenttime=datetime.today().strftime('%Y-%m-%d %H:%M:%S')
Z1S_Timestamp='2018-07-09 10:25:11'
if(currenttime==Z1S_Timestamp):
if(R8_1==1):
SetRelayState(BoardOne,8,"ON")
else:
SetRelayState(BoardOne,8,"OFF")
No matter how many times I changed the code, it will never work with this timing method. It never enters the loop and therefore the relay never opens. Is there a better way to do this rather than simply having if equal to statements? I am open to editing it, but the relays still need to open around the time of the start time. I think a margin of 1 or 2 minutes is okay, since timing it exactly equal is not 100% necessary.
Would something like:
currenttime= '2018-07-09 12:53:55' #hard coding just for example purposes
if('2018-07-09 12:52:55' <= currenttime <= '2018-07-09 12:54:55'):
do the things
Be a more valid/correct/pythonically correct method?
Sure - I would do the opposite though - convert all times to datetime() objects and use those for comparison:
TIME_MARGIN = datetime.timedelta(seconds=120) # use a margin of 2 minutes
time_compare = datetime.datetime(2018, 7, 9, 12, 52, 55)
current_time = datetime.datetime.now()
if (time_compare - TIME_MARGIN) < current_time < (time_compare + TIME_MARGIN):
#do something

Python, doing task 3 times a day while other stuff is happening?

So I have a task that occurs three times a day at a certain time that needs to be executed.
I've set up code that does this using a package called Schedule
https://pypi.python.org/pypi/schedule
What I like about this is I can say, run at 3:00AM every day, or something similar.
However, the issue is, I want my other code to be running at the same time, and not be stuck in the same loop that the Schedule is running in
So right now, it looks something like:
def archerPull():
#insert code for calling archer pull here
with open("LogsForStuffPull.txt", "a") as myfile:
myfile.write("time: " + time.ctime(time.time()))
#this is code for scheduling job to do every day
def schedulingTasks(firstTime, secondTime, thirdTime, fourthTime, fivthTime):
schedule.every().day.at(firstTime).do(archerPull)
schedule.every().day.at(secondTime).do(archerPull)
schedule.every().day.at(thirdTime).do(archerPull)
schedule.every().day.at(fourthTime).do(archerPull)
schedule.every().day.at(fivthTime).do(archerPull)
schedulingTasks("13:46", "13:47", "13:48", "13:49", "13:50")
while True:
schedule.run_pending()
time.sleep(1)
So as you can see, the loop will be True forever, and therefore run the scheduler everyday. But if I want to integrate other stuff with it, will it also be looped forever?
I want the tasks to be indivitual occuring (is asynchronous the word for it)
Please help me out, thanks!
Yeah, I figured this out the same day I asked this question
I used ap-scheduler to do this, my webapp in flask is running well while the backgrounds tasks I needed work great

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