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.
Related
Using pythons keyboard library,
I have two function definitions:
def start_tracking():
*code to start tracking time*
def end_tracking():
*code to stop tracking time*
I then want to use the same hotkey (e.g. F1) to invoke function 1 (start tracking time) on the first press and then function 2 (end tracking time) on the subsequent press. If I press the hotkey again after that, it should repeat the process.
Basically I want to use the same hotkey to track time and stop tracking time.
Here's what a working solution to start tracking time and stop tracking time using two different hotkeys looks like:
keyboard.add_hotkey("F1", start_tracking)
keyboard.add_hotkey("F2", end_tracking)
How can I accomplish the same thing with only one key (F1)?
I don't want to use a while loop because it slows down performance quite a bit.
Consider using a class variable or global variable as a flag. Such that:
class tracker():
def __init__(self):
self.start_flag = True <- Init class variable
def tracking(self):
if self.start_flag:
start_tracking()
self.start_flag = False #<- class variable toggling
else:
stop_tracking()
self.start_flag = True #<- class variable toggling
if name == '__main__'
x = tracker()
x.tracking() # starts tracker
time.sleep(5)
x.tracking() # stops tracker
Without more context on what your program is doing I can't say which is better. Typically globals should be avoided though. Simply put, you need a way to toggle which function is run. PS copypasting wont work. You will need to setup the class etc for proper usage. especially with where and how you defined start/stop. I would guess you are using globals but typically this should be avoided.
Solution:
def started():
start_tracking()
keyboard.remove_hotkey("F1")
keyboard.add_hotkey("F1", ended)
def ended():
end_tracking()
keyboard.remove_hotkey("F1")
keyboard.add_hotkey("F1", started)
#Hotkey
keyboard.add_hotkey("F1", started)
Basically I switch between the two events every time I press the hotkey by calling two functions in an alternating fashion.
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.
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!
I'm pretty new to Python, and coding in general, and currently working with Python 3.5. I wanted to learn to automate things that need text boxes filled to run. I experimented with the code below in a video game just as a way to learn.
I would like it to substitute different item numbers that are in a list into the consolecommand text.
Thank you for your time.
The code:
from pynput.keyboard import Key, Controller
import time
from keyboard import press
keyboard = Controller()
def submit():
press('enter')
def Keyboardpress1():
keyboard.press('/')
keyboard.release('/')
def waitone():
time.sleep(1)
def consolecommand():
keyboard.type("giveitem 172 49000")
def deepsix():
time.sleep(6)
def main():
deepsix()
submit()
waitone()
Keyboardpress1()
waitone()
consolecommand()
waitone()
submit()
deepsix()
if __name__ == '__main__':
main()
As you can see, the code is designed to hit a number to activate the command console in game, then type a command. The pauses between typing/keyboard are because the code doesn't run smoothly without them.
Thanks, appreciate any help.
Edit: I implemented fixes I learned from suggested resource materials. Now my problems are much fewer. Thank you, people of the comments section.
Edit1: I implemented new code to fix a previous problem. Now to get the consolecommand to change numbers.
#Connor Winterton, here's a very simplistic example of using a parameter to save repeating yourself. Consider func1() that performs a simple calculation and prints a hard-coded message. Consider func2() that is nearly the same except the message is different. By passing a parameter into func3() you can write just one function that will perform the task of both to reduce your code and clutter, and give you the ability to pass in any other messages you may want in the future:
def func1():
a = 1+2
print(a,'hello')
def func2():
a = 1+2
print(a,'goodbye')
def func3(my_msg):
a = 1+2
print(a,my_msg)
# call the hardcoded functions
func1()
func2()
# call the new versatile function
func3('hello')
func3('goodbye')
func3('See you later!')
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)