Threading with Python - python

complete python newbie...
I'm working with the Arduino pyfirmata package and Im trying to do something quite simple.
Depending on a user input to python, I want an LED to flash or not.
My problem is that the python program only asks for the user input once but I would like it to always ask for the input so the user can change function at any time.
I have tried using the threading package but no success... Perhaps there is a simpler way, but I am totally new to coding so I do not know of any other. Open to suggestions!!
Here is my code,
import pyfirmata
import threading
import time
board = pyfirmata.Arduino('/dev/cu.usbmodem14101')
def flash():
for i in range(1000):
board.digital[13].write(1)
time.sleep(1)
board.digital[13].write(0)
time.sleep(1)
def stop():
board.digital[13].write(0)
while True:
runMode = input("Run or Stop? ")
if runMode == "Run":
x = threading.Thread(target=flash(), args=(1,))
x.start()
# x.join()
elif runMode == "Stop":
x = threading.Thread(target=stop(), args=(1,))
x.start()
#x.join()

You can do it in an object-oriented way by creating your own Thread subclass something like the Flasher class below.
One of the advantages to this approach is that it would be relatively easy to extend the Flasher class and make it control LEDs connected to different outputs, or to allow the delay between flashes to be specified at creation time. Doing the former would allow multiple instances to be running at the same time.
import pyfirmata
import threading
import time
OFF, ON = False, True
class Flasher(threading.Thread):
DELAY = 1
def __init__(self):
super().__init__()
self.daemon = True
self.board = pyfirmata.Arduino('/dev/cu.usbmodem14101')
self.flashing = False
self.LED_state = OFF
def turn_LED_on(self):
self.board.digital[13].write(1)
self.LED_state = ON
def turn_LED_off(self):
self.board.digital[13].write(0)
self.LED_state = OFF
def run(self):
while True:
if self.flashing:
if self.LED_state == ON:
self.turn_LED_off()
else:
self.turn_LED_on()
time.sleep(self.DELAY)
def start_flashing(self):
if self.LED_state == OFF:
self.turn_LED_on()
self.flashing = True
def stop_flashing(self):
if self.LED_state == ON:
self.turn_LED_off()
self.flashing = False
flasher = Flasher()
flasher.start()
while True:
runMode = input("Run or Stop? ").strip().lower()
if runMode == "run":
flasher.start_flashing()
elif runMode == "stop":
flasher.stop_flashing()
else:
print('Unknown response ignored')

If your looking to just kill the thread you could use mulitiprocessing
which a multiprocessing.Process can p.terminate()
p = Process(target=flash, args=(,))
while True:
runMode = input("Run or Stop? ")
if runMode == "Run":
p.start()
elif runMode == "Stop":
p.terminate()
However this is not recommended to just kill threads as it can cause errors if the process is handling critical resources or dependant on other threads see here for a better explanation Is there any way to kill a Thread?
A better option as described here is to use flags to handle your flashing, they allow a simple communication between threads
from threading import Event
e = event()
def check_for_stop(e):
while not e.isSet():
flash()
print("Flashing Ended")
while True:
runMode = input("Run or Stop? ")
if runMode == "Run":
x = threading.Thread(target=check_for_stop, args=(e,))
x.start()
# x.join()
elif runMode == "Stop":
e.set() #set flag true
e.clear() #reset flag
here is the documentation for more info on event objects https://docs.python.org/2.0/lib/event-objects.html
I havent tested this code is just an example so apologies if it doesnt work straight away
Edit: Just looking at your function again you would want to check for the flag during the flashing thats my mistake aplogies so your flash function would look like
def flash():
while e.isSet():
board.digital[13].write(1)
time.sleep(1)
board.digital[13].write(0)
time.sleep(1)
and you would pass this into the thread as you have before
x = threading.Thread(target=flash(), args=(1,))
x.start()

You got an error in the code.
You should create the thread via:
x = threading.Thread(target=flash)
Note: You gave the entered 'flash()' therefore executing the method in the main thread. And also your method doesn't have any arguments therefore you can remove the args values

Related

How to use a changing variable value in a while loop | Python

I have a python program and a server that written with flask.
The thing I want to do is send a request to the server about is there any new order.
Server returns a JSON file as response if there is an active: True value in JSON should run my script. While script is running my program should continue to send request because while program running active value can be change to False. If active: False script should stop but I have to continue to send request to the server for checking the new orders.
I am adding an example below. If you have any question marks in your mind please let me know:
import time
def read_active_data():
pass
def my_func(active):
while True:
print("my_func is active")
if active == False:
break
count=0
active=False
while True:
if count%10==0:
active= read_active_data()
if active==True:
my_func(active)
time.sleep(1)
count+=1
I solved it like this:
from threading import Thread
import time
count=0
active= False
def set_active():
global active
global count
while True:
if count%10==0:
if active:
active=False
print("Inactive")
else:
active=True
print("Active")
time.sleep(1)
def kronos():
global count
while True:
time.sleep(1)
count+=1
print("Count is: ",count)
def execute():
global active
while True:
if active:
print("Executing")
else :
print("Not executing")
time.sleep(1)
if __name__ == '__main__':
t1 = Thread(target=set_active)
t2 = Thread(target=kronos)
t3 = Thread(target=execute)
t1.start()
t2.start()
t3.start()

Python how to do something when ..... in terminal

i'm initiating to python code and I need help :
How can I do a condition , if on the terminal , there is written like " {name} has said HEY " ?
Like if someone say HEY ( if it came out of the terminal ) , how I can transform it to a condition ?
Like " if HEY == on terminal "
print("Someone has said say !!!")
( I want to do this but with true python , Idk how to do It)
It looks like there is a similiar question answered at Looping until a specific key is pressed
I modified the code in the one I linked to modify a variable each time a key is was pushed in a specific order. I didn't make it where it had to be consecutive but after "h","e",&"y" are type in that order, it will stop with a printed message. There are a lot of ways to do this but this was the easiest way to show you that it can be done.
import keyboard
import time
import threading
class main:
def __init__(self):
# Create a run variable
self.run = True
# Start main thread and the break thread
self.mainThread = threading.Thread(target=self.main)
self.breakThread = threading.Thread(target=self.breakThread)
self.mainThread.start()
self.breakThread.start()
phrase = 'None'
def breakThread(self):
print('Break thread runs')
# Check if run = True
while True and self.run == True:
if keyboard.is_pressed('h'):
phrase = 'h'
if keyboard.is_pressed('e') and (phrase=='h'):
phrase = 'he'
if keyboard.is_pressed('y') and (phrase=='he'):
self.newFunction()
phrase = 'None'
break
def main(self):
print('Main thread runs')
# Also check if run = True
while not keyboard.is_pressed('esc') and self.run == True:
print('test')
time.sleep(2)
# Break like this
if keyboard.is_pressed('esc'):
break
print('test')
time.sleep(2)
def newFunction(self):
self.run = False
print('Password accepted')
print('You are in the new function!')
program = main()

How can you create a timer for an input?

For example:
# 5 second response, if user doesn't do it in 5 seconds, then quit()
a = input('Stack Overflow is cool')
if a == yes
print('Harold882')
else:
print('asdf')
How can you do that, or just make a timer in general?
I also tried making different timers, but they didn't work.
You could do something like this:
import time
from threading import Thread
answer = None
def check():
time.sleep(5)
if answer == None:
print("Too Slow")
elif answer == 'yes':
print('Harold882')
else:
print('asdf')
Thread(target = check).start()
answer = input("Stack Overflow is cool: ")
using the time and threading modules.

How to restart python multi-thread

I'm trying to design a control interface for my system which sends and receives some data through serial link. My searches related to GUI design took me to understand the "multi-threading" issue and code below shows the latest position I arrived.
This indicates similar parts (e.g try, run) with the ones I've seen on example GUIs. I planned to convert this to a GUI, once I understand how it exactly works.
So the problem is after I start, stop the code below I can't restart it again. Because, as I understand, multi-threading features only one cycle: start, stop and quit. I mean it doesn't accept start command after stop.
My question is how I can make this code to accept start after stopping?
Best wishes
import threading, random, time
class process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = 0
print("\n it's running ...\n\n")
while self.leave != 1:
print "Done!"
time.sleep(1)
operate = process()
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
operate.start()
elif int(inputt) == 0:
operate.leave = 1
elif int(inputt) == 2:
break
except:
print(" Wrong input, try egain...\n")
Create process inside while True loop
if int(inputt) == 1:
operate = process()
operate.start()
It should work.
... but your code may need other changes to make it safer - you will have to check if process exists before you try to stop it. You could use operate = None to control it.
import threading
import random
import time
class Process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = False
print("\n it's running ...\n\n")
while self.leave == False:
print("Done!")
time.sleep(1)
operate = None
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
if operate is None:
operate = Process()
operate.start()
elif int(inputt) == 0:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
operate = None
elif int(inputt) == 2:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
break
except:
print(" Wrong input, try egain...\n")
Other method is not to leave run() when you set leave = True but keep running thead. You would need two loops.
def run(self):
self.leave = False
self.stoped = False
print("\n it's running ...\n\n")
while self.leave == False:
while self.stoped == False:
print("Done!")
time.sleep(1)

Fabric get() progressbar

I am currently generating a python-script with the fabric framwork that is supposed to collect a backup from a remote server and store it locally on the client running fabric.
Now, since the backup file is >400MB, it takes quite some time to transfer it. And here is where my question bumps in:
Is there any kind of progressbars for the fabric get()-function? Or rather, is it possible to add a progressbar somehow?
Here's a piece of my code:
def collect_backup():
env.warn_only=True
run('uptime')
print "Copying scrips to be run..."
filename, remotepath = _getlatest()
print "Copy complete."
print "Collecting backup..."
localpath = _collect(filename, remotepath)
def _collect(filename, remotepath):
a=remotepath + filename
localpath="/home/bcns/backups/"
####Here's the get() I was talking about
get(a, localpath)
return(localpath)
The "filename" and "remotepath" variables are set in another function.
There is a lot of great info at the following site:
http://thelivingpearl.com/2012/12/31/creating-progress-bars-with-python/
Here is their solution for a console prog bar with threading:
import sys
import time
import threading
class progress_bar_loading(threading.Thread):
def run(self):
global stop
global kill
print 'Loading.... ',
sys.stdout.flush()
i = 0
while stop != True:
if (i%4) == 0:
sys.stdout.write('\b/')
elif (i%4) == 1:
sys.stdout.write('\b-')
elif (i%4) == 2:
sys.stdout.write('\b\\')
elif (i%4) == 3:
sys.stdout.write('\b|')
sys.stdout.flush()
time.sleep(0.2)
i+=1
if kill == True:
print '\b\b\b\b ABORT!',
else:
print '\b\b done!',
kill = False
stop = False
p = progress_bar_loading()
p.start()
try:
#anything you want to run.
time.sleep(1)
stop = True
except KeyboardInterrupt or EOFError:
kill = True
stop = True
Hope that helps or at least gets you started.

Categories

Resources