How to get Python to run display clear on keyboard interrupt - python

My Question is for the very end, I am trying to get the script to clear the display and disable the backlight when Control + C is pressed in linux, half of the time the lcd display will not clear
I have tried to get the python to close properly and clear the display but it only works a portion of time, even with sleep(1) added
#!/usr/bin/env python
import RPi.GPIO as GPIO
import lcd_driver
import socket
import struct
import fcntl
import time
import os
import re
from time import sleep
PIN = 23
COUNT = 0
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(PIN,GPIO.IN,pull_up_down=GPIO.PUD_UP)
print('Writing to Display!')
disp = lcd_driver.lcd()
def cputemp():
while True:
cputemp = os.popen("vcgencmd measure_temp").readline()
celsius = re.sub("[^0123456789/.]", "", cputemp)
fahrenheit = int(9.0/5.0*int(float(celsius)+32))
disp.lcdstring("Cpu : {} C".format(celsius), 1)
disp.lcdstring("Temp: {} F".format(fahrenheit), 2)
button = GPIO.input(PIN)
if button == False:
break
def curtime():
while True:
disp.lcdstring("Time: {}".format(time.strftime("%H:%M:%S")), 1)
disp.lcdstring("Date: {}".format(time.strftime("%m/%d/%Y")), 2)
button = GPIO.input(PIN)
if button == False:
break
def getaddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915,
struct.pack('256s', ifname[:15])
)[20:24])
def getip():
ip = getaddr('wlan0')
while True:
disp.lcdstring("IP Address: WiFi", 1)
disp.lcdstring(ip, 2)
button = GPIO.input(PIN)
if button == False:
break
try:
while True:
button = GPIO.input(PIN)
if button == True:
if COUNT == 0:
disp.lcdstring("Press the Button",1,0)
disp.lcdstring("To Start Demo!",2,1)
if COUNT == 1:
disp.clear()
cputemp()
if COUNT == 2:
disp.clear()
curtime()
if COUNT == 3:
disp.clear()
getip()
if COUNT == 4:
disp.clear()
COUNT = 1
if COUNT > 4:
disp.clear()
COUNT = 0
if button == False:
COUNT = COUNT +1
sleep(0.5)
except KeyboardInterrupt:
pass
finally:
disp.clear()
disp.backlight(0)
GPIO.cleanup()

import RPi.GPIO as GPIO
import lcd_driver
import socket
import struct
import atexit
import fcntl
import time
import os
import re
from time import sleep
def exit_handler():
print(' Cleaning Up!')
disp.clear()
disp.backlight(0)
GPIO.cleanup()
exit(1)
try:
while True:
button = GPIO.input(PIN)
if button == True:
if COUNT == 0:
disp.lcdstring("Press the Button",1,0)
disp.lcdstring("To Start Demo!",2,1)
if COUNT == 1:
disp.clear()
cputemp()
if COUNT == 2:
disp.clear()
curtime()
if COUNT == 3:
disp.clear()
getip()
if COUNT == 4:
disp.clear()
COUNT = 1
if COUNT > 4:
disp.clear()
COUNT = 0
if button == False:
COUNT = COUNT +1
sleep(0.5)
except KeyboardInterrupt:
pass
finally:
atexit.register(exit_handler)

You can add a shutdown hook using the atexit module
example code:
import RPi.GPIO as GPIO
import lcd_driver
import socket
import struct
import atexit
import fcntl
import time
import os
import re
from time import sleep
def exit_handler():
print(' Cleaning Up!')
disp.clear()
disp.backlight(0)
GPIO.cleanup()
exit(1)
atexit.register(exit_handler)
try:
while True:
button = GPIO.input(PIN)
if button == True:
if COUNT == 0:
disp.lcdstring("Press the Button",1,0)
disp.lcdstring("To Start Demo!",2,1)
if COUNT == 1:
disp.clear()
cputemp()
if COUNT == 2:
disp.clear()
curtime()
if COUNT == 3:
disp.clear()
getip()
if COUNT == 4:
disp.clear()
COUNT = 1
if COUNT > 4:
disp.clear()
COUNT = 0
if button == False:
COUNT = COUNT +1
sleep(0.5)
except KeyboardInterrupt:
pass
I use it on OrangePI to close a value when my code crash/exit and it works every time

Working code!!!
For Simplicity, being I can't vote yet
The difference is importing the atexit library
Adding in the event handler at top of code and replacing lcd.clear with lcd_driver.lcd()
And omitting the keyboard interrupt and following code to reflect how it is currently
#!/usr/bin/env python
import RPi.GPIO as GPIO
import lcd_driver
import socket
import struct
import atexit
import fcntl
import time
import os
import re
from time import sleep
PIN = 23
COUNT = 0
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(PIN,GPIO.IN,pull_up_down=GPIO.PUD_UP)
print('Writing to Display!')
disp = lcd_driver.lcd()
def exit_handler():
disp = lcd_driver.lcd()
disp.backlight(0)
GPIO.cleanup()
atexit.register(exit_handler)
def cputemp():
while True:
cputemp = os.popen("vcgencmd measure_temp").readline()
celsius = re.sub("[^0123456789/.]", "", cputemp)
fahrenheit = int(9.0/5.0*int(float(celsius)+32))
disp.lcdstring("Cpu : {} C".format(celsius), 1)
disp.lcdstring("Temp: {} F".format(fahrenheit), 2)
button = GPIO.input(PIN)
if button == False:
break
def curtime():
while True:
disp.lcdstring("Time: {}".format(time.strftime("%H:%M:%S")), 1)
disp.lcdstring("Date: {}".format(time.strftime("%m/%d/%Y")), 2)
button = GPIO.input(PIN)
if button == False:
break
def getaddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915,
struct.pack('256s', ifname[:15])
)[20:24])
def getip():
ip = getaddr('wlan0')
while True:
disp.lcdstring("IP Address: WiFi", 1)
disp.lcdstring(ip, 2)
button = GPIO.input(PIN)
if button == False:
break
try:
while True:
button = GPIO.input(PIN)
if button == True:
if COUNT == 0:
disp.lcdstring("Press the Button",1,0)
disp.lcdstring("To Start Demo!",2,1)
if COUNT == 1:
disp.clear()
cputemp()
if COUNT == 2:
disp.clear()
curtime()
if COUNT == 3:
disp.clear()
getip()
if COUNT == 4:
disp.clear()
COUNT = 1
if COUNT > 4:
disp.clear()
COUNT = 0
if button == False:
COUNT = COUNT +1
sleep(0.5)
except KeyboardInterrupt:
pass

Related

Python how to replace sleep with wait

I have a Python script where I would like to replace the sleep() with wait in order to interrupt the threads instantly even when they are sleeping.
However I don't know how to transform my functions into Events.
I read that asyncio could also be used but I am not sure to understand how it works.
Here is the code :
from pynput import keyboard
from pynput.keyboard import Key, Controller
import datetime
import time
import threading
import random
import pyautogui
from threading import Event
# --- functions ---
keyboardCtrl = Controller()
def run():
print('Running thread')
time.sleep(random.randrange(150,350)/1000)
while running:
my_keylist1=['e']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
#print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
time.sleep(random.randrange(10200,10450)/1000)
print('Exiting thread 1')
def run2():
time.sleep(random.randrange(150,350)/1000)
while running:
pyautogui.keyDown('z')
#print('T2',datetime.datetime.now())
#time.sleep(random.randrange(1000,3000)/1000)
print('Exiting thread 2')
pyautogui.keyUp('z')
def run3():
time.sleep(random.randrange(150,350)/1000)
while running:
my_keylist1=['f']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
#print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
time.sleep(random.randrange(6250,6550)/1000)
print('Exiting thread 3')
def on_press(key):
global running # inform function that it has to assign value to external variable
global clicker
global clicker2,clicker3
try: # PEP8: don't put it in one line - it make code unreadable for human
k = key.char
except:
k = key.name
if key == keyboard.KeyCode(char='q'):
print("Key Pressed")
if not running: # the same as `if running == False:`
print("Starting thread")
clicker = threading.Thread(target=run)
clicker2 = threading.Thread(target=run2)
clicker3 = threading.Thread(target=run3)
running = True # it has to be before `start()`
clicker.start()
clicker2.start()
clicker3.start()
else:
print("Stopping thread")
running = False # it has to be before `join()`
clicker.join()
clicker2.join()
clicker3.join()
# press `F1` to exit
if key == keyboard.Key.f1:
return False
# --- main ---
running = False # default value at start
try:
print("Starting program")
print("- press E to start/stop thread")
print("- press F1 to exit")
print("- press Ctrl+C to exit")
lis = keyboard.Listener(on_press=on_press)
lis.start()
print("Listening ...")
lis.join()
print("Exiting program")
except KeyboardInterrupt:
print("Stoped by Ctrl+C")
else:
print("Stoped by F1")
finally:
if running:
running = False
clicker.join()
clicker2.join()
clicker3.join()
Maybe you can try something like, I am sure there is a better solution, I would suggest reading the documentation.
import asyncio
from pynput import keyboard
from pynput.keyboard import Key, Controller
import datetime
import time
import threading
import random
import pyautogui
from threading import Event
# --- functions ---
keyboardCtrl = Controller()
async def run():
print('Running thread')
await asyncio.sleep(random.randrange(150, 350) / 1000)
while running:
my_keylist1 = ['e']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
# print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
#time.sleep(random.randrange(10200, 10450) / 1000)
await asyncio.sleep(random.randrange(10200, 10450) / 1000)
print('Exiting thread 1')
async def run2():
#time.sleep(random.randrange(150, 350) / 1000)
await asyncio.sleep(random.randrange(150, 350) / 1000)
while running:
pyautogui.keyDown('z')
# print('T2',datetime.datetime.now())
# time.sleep(random.randrange(1000,3000)/1000)
print('Exiting thread 2')
pyautogui.keyUp('z')
async def run3():
#time.sleep(random.randrange(150, 350) / 1000)
await asyncio.sleep(random.randrange(150, 350) / 1000)
while running:
my_keylist1 = ['f']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
# print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
#time.sleep(random.randrange(6250, 6550) / 1000)
await asyncio.sleep(random.randrange(6250, 6550) / 1000)
print('Exiting thread 3')
async def on_press(key):
global running # inform function that it has to assign value to external variable
global clicker
global clicker2, clicker3
try: # PEP8: don't put it in one line - it make code unreadable for human
k = key.char
except:
k = key.name
if key == keyboard.KeyCode(char='q'):
print("Key Pressed")
if not running: # the same as `if running == False:`
print("Starting thread")
#await run()
#await run2()
#await run3()
await asyncio.gather(*[run(), run2(), run3()])
#clicker = threading.Thread(target=run)
#clicker2 = threading.Thread(target=run2)
#clicker3 = threading.Thread(target=run3)
running = True # it has to be before `start()`
#clicker.start()
#clicker2.start()
#clicker3.start()
else:
print("Stopping thread")
running = False # it has to be before `join()`
#clicker.join()
#clicker2.join()
#clicker3.join()
# press `F1` to exit
if key == keyboard.Key.f1:
return False
# --- main ---
running = False # default value at start
def main(*args, **kwargs):
asyncio.run(on_press(args[0]))
try:
print("Starting program")
print("- press E to start/stop thread")
print("- press F1 to exit")
print("- press Ctrl+C to exit")
lis = keyboard.Listener(on_press=main)
lis.start()
print("Listening ...")
lis.join()
print("Exiting program")
except KeyboardInterrupt:
print("Stoped by Ctrl+C")
else:
print("Stoped by F1")
finally:
if running:
running = False
#clicker.join()
#clicker2.join()
#clicker3.join()

How to make my loop start and stop with key presses in python?

My code will start (pressing p) and stop (pressing o) the loop once, but won't start the loop again, what am I doing wrong?
import pyautogui, time, keyboard
while True:
if keyboard.is_pressed('p'):
print("Rodando")
x=0
while True:
if x == 0:
pyautogui.press("F7")
pyautogui.press("F7")
print("a")
time.sleep(0.1)
pyautogui.press("F7")
pyautogui.press("F7")
print("b")
time.sleep(0.5)
if keyboard.is_pressed('o'):
print("abortando")
x = 1
Try this code.
import pyautogui, time, keyboard
A = False
def start_loop():
global A
while True:
if keyboard.is_pressed('p') or A:
print("Rodando")
A = True
x=0
while True:
if x == 0:
pyautogui.press("F7")
pyautogui.press("F7")
print("a")
time.sleep(0.1)
pyautogui.press("F7")
pyautogui.press("F7")
print("b")
time.sleep(0.5)
if keyboard.is_pressed('o'):
print("abortando")
x = 1
A = False
break
start_loop()
start_loop()
keyboard module does not always work if this happens then please press the key again😊.

How do I find the last sector of harddisk?

I have not tried to find the last sector by multiplying the number of sectors by 10. I tried to find it by increasing 1 but the system was very tired and took a lot of time. I don't want to filter out the output of ready commands.
How can I find the number of cylinders, heads and sectors. I think I will get the number of sectors by converting from chs system to lba system.
import os
def main():
s=1
if os.name == "nt":
while True:
if read_sector(r"\\.\physicaldrive0",s)=='':
break
else:
s=s*10
print(s)
else:
while True:
if read_sector("/dev/sda",s)=='':
break
else:
s=s*10
print(s)
def read_sector(disk, sector_no=0):
f = open(disk, 'rb')
f.seek(sector_no * 1)
read = f.read(1)
return read
if __name__ == "__main__":
main()
or
import os
def main():
s=0
if os.name == "nt":
while True:
if read_sector(r"\\.\physicaldrive0",s)=='':
break
else:
s=s+1
print(s)
else:
while True:
if read_sector("/dev/sda",s)=='':
break
else:
s=s+1
print(s)
def read_sector(disk, sector_no=0):
f = open(disk, 'rb')
f.seek(sector_no * 1)
read = f.read(1)
return read
if __name__ == "__main__":
main()
import os
def end_sector(disk):
os.system("fdisk -l %s >fdisk.lst"%disk)
with open("fdisk.lst") as file:
dosya=file.read()
dosya=dosya.split()
j=0
for i in dosya:
j=j+1
for i in range(j):
if dosya[i]=="sektör":
max_sector=int(dosya[i-1])
for i in range(j):
if dosya[i]=="=" and dosya[i-1]==dosya[i+1]:
sector_size=int(dosya[i+1])
return max_sector,sector_size
dizi=end_sector("/dev/sdb")
print(dizi)

Run these two sections at once Python

I have some Python for a Raspberry Pi where I test for a button press (first loop) and use it to start and stop a timer (second loop). However, if I run this program only the first loop in the sequence runs. How can I make it so both run at the same time? Code:
EDIT: made changes to code in attempt to accommodate threading. Would this work?
import os
os.chdir('/home/pi/Desktop/Python')
import lcd
lcd.lcd_init()
import time
import threading
from threading import Thread
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN, pull_up_down=GPIO.PUD_UP)
latest_state = None
status = False
seconds = 0
minutes = 0
hours = 0
def button():
while True:
if status == True:
seconds +=1
if seconds == 59:
seconds = 0
minutes = minutes + 1
if minutes == 59:
minutes = 0
hours = hours + 1
tup = " H:",hours," M:",minutes," S:",seconds
display = ''.join(map(str, tup))
lcd.lcd_string(display,2)
time.sleep(0.99)
Thread(target = button).start()
while True:
inputValue = GPIO.input(23)
if inputValue != latest_state:
latest_state = inputValue
if latest_state:
print " "
else:
status = not status
print status
print " "

Interrupt python script with a specific key on Linux

I'm trying to have a loop which increments and prints a value. While it's running I would like to press a key (eg. space or shift) and have it print that the key was pressed. Below is example code of what I would like.
def space():
print 'You pressed space'
def shift():
print 'You pressed shift'
x = 0
while True:
print(x)
#if space is pressed
space()
#if shift is pressed
shift()
x = x + 1;
time.sleep(1)
EDIT: Here is an example output
0
1
2
You pressed shift
3
4
5
You pressed space
6
7
.
.
.
I can help you with modified answer form here:
https://stackoverflow.com/questions/11918999/key-listeners-in-python
and for only space and enter:
import contextlib
import sys
import termios
import time
#contextlib.contextmanager
def raw_mode(file):
old_attrs = termios.tcgetattr(file.fileno())
new_attrs = old_attrs[:]
new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
try:
termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs)
yield
finally:
termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs)
def space(ch):
if ord(ch) == 32:
print 'You pressed space'
def enter(ch):
if ord(ch) == 10:
print 'You pressed enter'
def main():
print 'exit with ^C or ^D'
with raw_mode(sys.stdin):
try:
x = 0
while True:
print(x)
ch = sys.stdin.read(1)
space(ch)
enter(ch)
x = x + 1;
time.sleep(1)
except (KeyboardInterrupt, EOFError):
pass
if __name__ == '__main__':
main()
If you're on windows, check out msvcrt:
import msvcrt
while True:
x += 1
sleep(x)
if msvcrt.kbhit():
print "You pressed: %s" % msvcrt.getch()

Categories