Scanning Keypress in Python - python

I have paused a script for lets say 3500 seconds by using time module for ex time.sleep(3500).
Now, my aim is to scan for keypresses while the script is on sleep, i mean its on this line.
Its like I want to restart the script if a "keypress Ctrl+R" is pressed.
For ex.. consider
#!/usr/bin/python
import time
print "Hello.. again"
while True:
time.sleep(3500)
Now while the code is at last line, If i press Ctrl+R, i want to re-print "Hello.. again" line.

I am aware that this does not fully answer your question, but you could do the following:
Put the program logic code in a function, say perform_actions. Call it when the program starts.
After the code has been run, start listening for an interrupt.
That is, the user must press ctrl+c instead of ctrl+r.
On receiving an interrupt, wait half a second; if ctrl+c is pressed again, then exit.
Otherwise, restart the code.
Thus one interrupt behaves as you want ctrl+r to behave. Two quick interrupts quit the program.
import time
def perform_actions():
print("Hello.. again")
try:
while True:
perform_actions()
try:
while True: time.sleep(3600)
except KeyboardInterrupt:
time.sleep(0.5)
except KeyboardInterrupt:
pass
A nice side-effect of using a signal (in this case SIGINT) is that you also restart the script through other means, e.g. by running kill -int <pid>.

You may want to use Tkinter {needs X :(}
#!/usr/bin/env python
from Tkinter import * # needs python-tk
root = Tk()
def hello(*ignore):
print 'Hello World'
root.bind('<Control-r>', hello)
root.mainloop() # starts an X widget
This script prints Hello World to the console if you press ctrl+r
See also Tkinter keybindings. Another solution uses GTK can be found here

in a for loop sleep 3500 times for 1 second checking if a key was pressed each time
# sleep for 3500 seconds unless ctrl+r is pressed
for i in range(3500):
time.sleep(1)
# check if ctrl+r is pressed
# if pressed -> do something
# otherwise go back to sleep

Related

Break loop using hotkey

There are hundreds of similar questions but none of them appear to be a solution in my case.
My code is shaped in this way
def iterative_func():
# do things
while True:
iterative_func()
Then I would like it to stop when I press a hotkey let's say 'ctrl+k'.
I tried pynput but the listener is not applicable since it waits for an Input and the rest of the script (iterative_func()) won't run, in my case the script should continuously run until I press some hotkey.
Also the solution
while True:
try:
iterative_func()
except KeyboardInterrupt:
break
doesn't work for me (I don't know why, but maybe it's because I'm running VSCode), anyway it's not code I want to implement because the script will be deployed as a .exe file.
PS.
I cannot import Key and Controller from pynput, it prompts an error and I have no clue on how to fix this so also solutions using these should be avoided.
I tried pynput but the listener is not applicable since it waits for
an Input and the rest of the script (iterative_func()) won't run
I can shed some light on how to overcome this problem, which made you optout pynput. See the below approach:
from pynput import keyboard
running = True # flag on loop runs
def stop_run(): # function to stop the program
global running
running = False
# register a hotkey, and call stop_run() when it is pressed
with keyboard.GlobalHotKeys({'<ctrl>+k': stop_run}) as h:
while running:
print("Running ... ")
This will run your code and wait for hotkey to stop the loop by a flag.

python urwid timeout on idle

Is there a way to have a urwid app to do a sys.exit() after a configurable timeout if no input has been received from the user in more than 30 seconds?
We are facing network outages and that leads to the SSH Session being dropped but the client program keeps running and holds a Database lock and manually killing is the only option for now and hence this requirement.
You can set an alarm in the main loop that will call whatever code you want when it times out. Here I call a function that uses the ExitMainLoop exception, but sys.exit() would also work.
This code cancels the previous alarm (if any) when keyboard input happens, then sets a new alarm. As long as keys are coming in, the alarm should never go off.
Internally, as of late 2020, for alarms urwid seems to use Python's time.time(), which is not guaranteed to only go forward one-second-per-second. The alarm might go off early, exiting the program, if the system clock gets adjusted forward (by NTP?).
import urwid
timeout_time=30
def urwid_exit(loop, user_data):
raise urwid.ExitMainLoop
def handle_input(input):
global txt
global loop
#don't reset the alarm on a mouse click,
# and don't try to display it (the .set_text would error if given a tuple)
if not type(input) is tuple:
if hasattr(handle_input, "last_alarm") and handle_input.last_alarm:
loop.remove_alarm(handle_input.last_alarm)
handle_input.last_alarm = loop.set_alarm_in(timeout_time, urwid_exit)
txt.set_text("key pressed: %s" % input)
txt = urwid.Text("Hello world")
fill = urwid.Filler(txt, 'top')
loop = urwid.MainLoop(fill, unhandled_input=handle_input)
#call handle input once without any input to get the alarm started
handle_input(None)
loop.run()
A slight variation on StephenK's answer is to use loop.event_loop.enter_idle(callback) instead of unhandled_input. The callback function will be run whenever urwid enters an idle state, including after processing a keypress event. This is somewhat more general: the timer starts after all activity has finished. (Say, the last keypress starts an action that takes many seconds to finish)
The relevant documentation is at
https://urwid.readthedocs.io/en/latest/reference/main_loop.html
import urwid
timeout = 10
txt = urwid.Text(
'This program will exit after '
f'_{timeout}_ seconds of inactivity '
'(no keypresses, etc)\n',
align='center'
)
fill = urwid.Filler(txt, 'top')
loop = urwid.MainLoop(fill)
alarm_handle = None
def alarm_callback(_loop, _user_data):
raise urwid.ExitMainLoop
def idle_callback():
global alarm_handle
loop.remove_alarm(alarm_handle) # remove old alarm
alarm_handle = loop.set_alarm_in(timeout, alarm_callback)
text = txt.get_text()[0] + f"\nAlarm has been reset _{alarm_handle[1]}_ times"
txt.set_text(text)
loop.event_loop.enter_idle(idle_callback)
loop.run()

How to exit a Python program or loop via keybind or macro? Keyboardinterrupt not working

I am trying to complete a simple GUI automation program that merely opens a web page and then clicks on a specific spot on the page every 0.2 seconds until I tell it to stop. I want my code to run and have its loop run infinitely until a keybind I specify breaks the loop (or entire program). I started out with the classic, KeyboardInterrupt, which enables CTRL+C to exit a program. Here is what I thought my final code would look like:
import webbrowser, pyautogui, time
webbrowser.open('https://example.com/')
print('Press Ctrl-C to quit.')
time.sleep(5)
#pyautogui.moveTo(1061, 881)
try:
while True:
time.sleep(0.2)
pyautogui.click(1061,881)
except KeyboardInterrupt:
print('\nDone.')
Everything about the code works, except the fact that I can't exit it once the clicking loop starts. Keyboard interrupt and using CTRL-C to exit do not work at all for this script, for whatever reason.
I merely want to be able to press "escape" (or any other key) to exit the loop (or the program altogether) - just any way to make the loop exit and stop. Right now it runs ad infinitum, but I want a simple keybind macro to be able to stop/break it.
I've tried using getch to keybind the escape key to cause a break, but to no avail:
import webbrowser, pyautogui, time, msvcrt
webbrowser.open('https://example.com')
print('Press Ctrl-C to quit.')
time.sleep(5)
#pyautogui.moveTo(1061, 881)
try:
while True:
time.sleep(0.2)
pyautogui.click(1061,881)
if msvcrt.kbhit():
key = ord(readch())
if key == 27:
break
I'm surprised it's been so hard to do this in Python. I've checked out a lot of similar problems across Stackoverflow, but with unsatisfactory answers, and none that solve my problem, unfortunately. I've been able to do things like this in simpler coding languages like AuotHotKeys with ease. I feel like I'm dancing around the solution. Any and all help would be wonderfully appreciated! Thanks in advance.
If I understood correctly, you want to be able to stop your program by pressing a key on your keyboard.
To make you create a thread that will check in background if you press the key in question.
A little example:
import threading, time
from msvcrt import getch
key = "lol"
def thread1():
global key
lock = threading.Lock()
while True:
with lock:
key = getch()
threading.Thread(target = thread1).start() # start the background task
while True:
time.sleep(1)
if key == "the key choosen":
# break the loop or quit your program
Hope its help.

Python Hello World keeps closing itself

I'm new to programming. I''ve successfully wrote everybody's first program , however , it executes right before closing itself. How can I add a pause to the program?
Modify the code to be like this, you will learn about the below function soon enough:
print('Hello world!')
input()
Now at the end of the program it won't exit until you press Return.
Or better still, run the code in a shell like IDLE so you don't have to worry about all that.
You need to put a call to input at the bottom of your script:
print("Hello World!")
input("Press 'Enter' to exit.") # Use raw_input in Python 2.x
Doing so will keep the output window open until you press Enter.
If you literally want to add a fixed pause, use the sleep function in the time module. The is discussed in detail in the answer to How can I make a time delay in Python? . Your program then becomes:
import time
print("Hello world")
time.sleep(1)
The first line tells python that time means the module time, while the last line says to wait for 1 second. (If you wanted to wait for 2.5 seconds, then change the last line to time.sleep(2.5), etc...)

keybord interrupt event listener

I have a problem with my script. i want do do an event listender for the whole script from beginning to the end.
if someone presses ctrl-c or something it should ignore, or end the scipt with an print.
I can show you my code if needed.
I tried signal and sys but I didnt know how to use it right
A simple approach for ending the script with a print could be to wrap the whole script in a try/except block:
import sys
try:
while 1:
print 'To infinity and beyond!'
# etc etc...
except KeyboardInterrupt:
print 'Handling the keyboard interrupt...'
The interrupt still kills the script, but I would think this is desired behaviour for any user; personally I wouldn't recommend trying to override it.

Categories

Resources