My script runs once, how do I code it to run always? - python

I'm new to python and programming in general. I made a small script that gives me a notification when the battery reaches 100% or goes below 25%. It runs fine for a single instance. I'm trying to get it to always run i.e. that it sits in the tray and popups up the notification as per the conditions. I tried putting the whole thing through a "while True:" loop but that does not seem to help. Could you guys help me out?
Code:-
import psutil
from win10toast import ToastNotifier
toaster=ToastNotifier()
while True:
def battery():
val=psutil.sensors_battery()
percent=val.percent
power=val.power_plugged
if percent<25 and power==False:
return ('We\'re low on power({}%),plug in the charger.'.format(percent))
elif percent>=100 and power==True:
return ('Fully charged ({}%),you can disconnect the charger now.'.format(percent))
try:
toaster.show_toast('BatteryMeter',battery(),'c:/users/sanoop/desktop/Battery.ico',duration=5)
except:
pass```

You need to routinely call the battery() in while, nothing else.
So, for example, considering the rest of your code remains the same:
while True:
battery()
time.sleep(1)

Related

Python multiprocessing process hangs at the end of it

I have a python script driving me crazy.
Right now i have a infinite loop that checks a data and get into a function in a specific situation.
while true:
time.sleep(1)
peso = getPeso()
if peso > 900:
processo = multiprocessing.Process(target=processo_automatico)
processo.start()
processo.join()
andare() #this is where it should go after the process.
The function works a lot of times but nondeterministically it hangs at the end of the process (literally finish and hangs there forever. How do i know this? i tried with logs).
So at the beginning I tried to terminate it with exit codes:
processo.join(timeout=10)
if processo.exitcode is None:
errore_cicalino() #this is just a warning for me
processo.kill()
elif processo.exitcode != 0:
errore_cicalino()
processo.kill()
but this never worked. NEVER.
So i tried without the join(). Tried with is_alive().
time.sleep(10)
if processo.is_alive():
processo.terminate()
errore_cicalino()
and even like this, it never entered this if.
This is driving me crazy, i accept the fact that the process could fail but, after the timeout, i should be able to terminate it and carry on with the script.
The script is running on a Raspberry Pi 4 2 GB.
Any idea?
Minimal example:
while True:
time.sleep(10)
processo = multiprocessing.Process(target=processo_automatico)
processo.start()
processo.join()
code randomly hangs at the end of the started process and cannot terminate in any way.
processo_automatico() is a function where the script get a picture from a camera and upload it in a DB thanks to another module.
def processo_automatico():
now = str(datetime.now())
now = now.replace(":", "-")
foto = CAMERA.read_camera()
cv2.imwrite("/var/www/html/" + now + ".png", foto)
DB.insert("/var/www/html/" + now + ".png", peso)
They don't create exceptions and i already tried to add to the end of the function a log info(executed even when the code hangs)
Solved.
What was that?
Well, my focus was on the end of the process while the issue was right at the start.
See the function getPeso()? That one just gets values from the serial.
After a few hours of getting those values the raspberry py just starts to see random values and you gotta reboot to fix it.
I wasn't prepared for that. My function just became a recursive infinite function with no break.
My tip, do not use infinite cycles except if you really need to or at least think if it could get stuck somewhere and check it.

How to pause/sleep() function without crashing app?

I have an app I'm trying to add website updates to every minute. That part works just fine at the moment. The problem I'm experiencing with this current excerpt of code is that, when I go to close/exit the app, I have to hit the "X" button a few times and it completely crashes and freezes.
If my understanding is correct, I believe that is happening because time.sleep() is still "running" constantly when I try to exit.
How can I run a regular update like this that wont throw the app into a fit when I want to close it? Can someone please help me with a solution here?
I have added just a 5 second sleep in this working example here instead of my intended 60 seconds to save time when you test it.
import time
from threading import Thread
from kivy.app import App
class Test(App):
def build(self):
self.thread_for_update()
def thread_for_update(self):
p1 = Thread(target=lambda: self.check_for_update())
p1.start()
def check_for_update(self):
time.sleep(5)
print("Update")
# Here I'm checking an online data source for changes
# I will also notify user if theres changes
self.thread_for_update()
Test().run()
You could use threading.Timer, and update it in another function.
threading.Timer takes 2 argument, the delay (in seconds) and the function to call.
def check_for_update(self):
Timer(5, self.update).start()
def update(self):
print("Update")
self.thread_for_update()
I think I may have fixed it. when I add p1.daemon = True it seems to exit the program well when I try to exit.

Tkinter - Creating a responsive GUI with a progressbar

Using PyGubu (tool to create Tkinter interfaces) I obtained the following GUI:
Current situation:
When I click the Button "Create", a function is called. This function takes quite some time, and the graphical interfaces is just frozen. As I would like to keep the graphical interface and the functional part as much separated as possible, I don't want to update the Progress Bar or the interface in general from the function I call
Desired situation
The best case for me would be a solution without Threading: I would like, upon clicking "Create", that my function runs, while the Progress Bar updates itself (just to show a feedback to the user, and to tell him "look, I am doing something") and the interface remains responsive, so the user can actually interact with it while the function finish.
Current attempts
I tried to solve this using Threading:
#I have this code in my main.py:
from threading import Thread
from queue import Queue, Empty
my_queue=Queue()
#And this is a simplified version of the Command of the "Create" Button:
def create_command(self):
#Show the progress bar and start it
self.show_item(self.progress)
self.progress.start()
#Run the big function
thrd = Thread(target = my_big_function, args=(some_arguments, my_queue))
thrd.start()
do_retry = True
while do_retry: #Repeat until you have a result
try:
result = my_queue.get(False) #If you have a result, exit loop. Else, throw Empty
do_retry = False
except Empty: #Queue is still empty
self.progress_var.set(self.progress_var.get()+1)
sleep(0.05)
self.mainwindow.update() #Update the progress bar
q.task_done()
self.progress.stop()
Problem of the current attempt
As I am not used to work with threads, I am facing two problems:
In some runs (not all of them, just some) I have a RuntimeError stating
RuntimeError: main thread is not in main loop
I tried to overcome this looking at other question in StackOverflow, but now it just happens randomly, and I don't know how to avoid it. The module mtTinker is no more maintained for python 3.x (there is a vague attempt full of ToDoes and blood)
If there is some kind of exception in the big function, I don't know how to handle it. The program would just run forever waiting for a result that will never come back
So
How can I obtain my desired outcome? Thanks in advance
You can try adding root.update() inside the function you call, inside the main loop. Hope that's helpful!

Multiprocessing from a class

I am new to python programming, and I would like to make a class module for stepper motors. I want to have a function inside the class that makes the stepper motor run forever, and another function to stop it.
from steppermotor import stepper
import time
MotorA = stepper(1) # argument is for port, not important
MotorB = stepper(2)
MotorA.forward(2) # stepsize, not important
MotorB.forward(2)
time.sleep(5)
MotorA.stop()
MotorB.Stop()
The time.sleep(5) can be replaced with anything. The point is I want to be able to do something else while those two motors are running. Is there a way that I could do this without having to put the subprocessing in the main program, but in the steppermotor.py program? Example with using loops and prints would be appreciated. Thank you.

Python 2.X / Tkinter needs print to run

Firstly, very much Py Newby!
I have written a program to import data from a file and display it as an image using tkinter. The loop that is misbehaving runs thus:
Get data and plot
for x in xrange(WIDE):
for y in xrange(HIGH):
dataPointLo = inFile.read(1)
dataPointHi = inFile.read(1)
pixelValue = ((ord(dataPointLo) + 256*(ord(dataPointHi)))-31500)
colour = rgb[pixelValue]
#print below makes prog run!
print pixelValue
img.put(colour, to=(x,y))
As suggested by the comment, leaving out the print stops it working, but it locks one core of the processor at 100% for as long as you leave it (well at least 20 mins!). This effect occurs both in IDLE and from the command line (Ubuntu 12.04). Of course, the print to the IDLE window slows the program down, so I would like to remove it! Any thoughts?
it sounds like the process you are running takes a long time to complete, i would suggest that the reason you think it stops is because the window doesn't update while the process is busy unless you tell it to. i suggest you add a function like the following to your code and call it once before you enter your loop:
def keep_alive(self):
self.update()
self.after(100, self.keep_alive)
this way you are adding an event to update the window every 100ms(ish) to the event loop, which will keep the program responsive. you can adjust the timing to suit you, too often will slow your loop down, too far apart and the program will feel sluggish.

Categories

Resources