Put simply, I'm trying to figure out how to run some code when the PyAutoGUI failsafe executes. I've tried searching this problem many times and can't figure out a way to do it.
This is what I want:
Move mouse to corner and provoke failsafe.
Right before program ends from fail safe, runs line of code.
Program completely closes.
The pyautogui.FailSafeException is raised when the mouse is moved to the upper left corner (x,y of 0, 0). You could catch this exception and run code from there:
import pyautogui
import sys
while True:
try:
pyautogui.moveTo() # Any PyAutoGUI (without side effects) call will do here.
except pyautogui.FailSafeException:
print('Running code before exiting.') # Your code here.
sys.exit()
Related
This is two questions really:
how do I resize a curses window, and
how do I deal with a terminal resize in curses?
Is it possible to know when a window has changed size?
I really can't find any good doc, not even covered on http://docs.python.org/library/curses.html
Terminal resize event will result in the curses.KEY_RESIZE key code. Therefore you can handle terminal resize as part of a standard main loop in a curses program, waiting for input with getch.
I got my python program to re-size the terminal by doing a couple of things.
# Initialize the screen
import curses
screen = curses.initscr()
# Check if screen was re-sized (True or False)
resize = curses.is_term_resized(y, x)
# Action in loop if resize is True:
if resize is True:
y, x = screen.getmaxyx()
screen.clear()
curses.resizeterm(y, x)
screen.refresh()
As I'm writing my program I can see the usefulness of putting my screen into it's own class with all of these functions defined so all I have to do is call Screen.resize() and it would take care of the rest.
I use the code from here.
In my curses-script I don't use getch(), so I can't react to KEY_RESIZE.
Therefore the script reacts to SIGWINCH and within the handler re-inits the curses library. That means of course, you'll have to redraw everything, but I could not find a better solution.
Some example code:
from curses import initscr, endwin
from signal import signal, SIGWINCH
from time import sleep
stdscr = initscr()
def redraw_stdscreen():
rows, cols = stdscr.getmaxyx()
stdscr.clear()
stdscr.border()
stdscr.hline(2, 1, '_', cols-2)
stdscr.refresh()
def resize_handler(signum, frame):
endwin() # This could lead to crashes according to below comment
stdscr.refresh()
redraw_stdscreen()
signal(SIGWINCH, resize_handler)
initscr()
try:
redraw_stdscreen()
while 1:
# print stuff with curses
sleep(1)
except (KeyboardInterrupt, SystemExit):
pass
except Exception as e:
pass
endwin()
This worked for me when using curses.wrapper():
if stdscr.getch() == curses.KEY_RESIZE:
curses.resizeterm(*stdscr.getmaxyx())
stdscr.clear()
stdscr.refresh()
It isn't right. It's an ncurses-only extension. The question asked about curses. To do this in a standards-conforming way you need to trap SIGWINCH yourself and arrange for the screen to be redrawn.
So, I was just messing around with pyautogui moving the mouse to random positions on the screen, when I manually moved the mouse to the top left corner of the screen and ran the program, it raised a pyautogui failsafe.
I do know how to disable it and all that, but I want to know why is is there in the first place and possible use cases
Code:
import pyautogui
pyautogui.click(x=25, y=1048)
time.sleep(2) # I moved the move to the corner of the screen during this time delay
pyautogui.click(x=701, y=430)
Error:
Traceback (most recent call last):
File "C:\1 Files and Folders\folder\Python Project\Python\CODE\My Projects\Automation.py", line 23, in <module>
job()
File "C:\1 Files and Folders\folder\Python Project\Python\CODE\My Projects\Automation.py", line 18, in job
pyautogui.click(x=1475, y=141)
File "C:\Users\My_user\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pyautogui\__init__.py", line 585, in wrapper
failSafeCheck()
File "C:\Users\My_user\AppData\Local\Programs\Python\Python39-32\lib\site-packages\pyautogui\__init__.py", line 1710, in failSafeCheck
raise FailSafeException(
pyautogui.FailSafeException: PyAutoGUI fail-safe triggered from mouse moving to a corner of the screen. To disable this fail-safe, set pyautogui.FAILSAFE to False. DISABLING FAIL-SAFE IS NOT RECOMMENDED.
According to pyautogui docs
It’s hard to use the mouse to close a program if the mouse cursor is
moving around on its own.
As a safety feature, a fail-safe feature is enabled by default. When a
PyAutoGUI function is called, if the mouse is in any of the four
corners of the primary monitor, they will raise a
pyautogui.FailSafeException.
So simply FailSafe is just thing that if your program just spams the mouse or doing something that you cannot stop it, You can close that in this way, For more information read it docs pyautogui docs
Reset
pyautogui.FAILSAFE = False
at the beginning of ur script.
I'm building a headless soundboard using Raspberry Pi, and as such need a way to launch the script I'm using on boot. The program was edited and tested using the default editor Pi shot up, Thonny, and everything seems to run as intended. The buttons I'm using all play the sounds I expect them to, no issues.
I went ahead and edited rc.local to run the script as soon as the Pi boots (specifically, I added sudo python /filepath/soundboard.py & above exit 0), which it does. It seems to run identically to the way it did using Thonny, but sound cuts off after about 5 seconds, even if no buttons are pressed. When I run it directly through the command line, the same issue occurs.
The code here has been compressed, as there is more than one button, but they all use the same line.
import pygame
import random
import glob
from gpiozero import Button
import time
pygame.init()
while True:
n = glob.glob('/filepath/*.wav')
btn_0 = Button(8)
btn_0.when_pressed = pygame.mixer.stop
btn_0.when.held = lambda: pygame.mixer.Sound(random.choice(n)).play()
As far as I can tell, the while loop continues to run the program, but pressing buttons does nothing. Also, since adding the loop, the code dumps a Traceback, showing the error
gpiozero.exc.GPIOPinInUse: pin 8 is already in use by <gpiozero.Button objext on pin GPIO8, pull_up=True, is_active=False>
which might have something to do with my issue? btn_0 isn't the only button to have two functions assigned to it, but the only one to throw up this error, no matter what pin I use. The error doesn't appear if I remove the loop from the code.
You create btn_0 in an infinit while loop again and again. In the second iteration btn_0 is probably the first button that is created again. But pin 8 (which should be used for the button) has been assigned to the old instance of btn_0 in the last iteration.
You should move the glob.glob statement and the button initialization outside of the While loop. If the while loop is necessary to keep you program running place it below the initialization code and iterate over nop ore pause statements (whatever works).
If pygame.init starts it own looped thread you do not need a while loop at the end at all.
I don't know anything about pygame, so the last statement is just a guess.
Example:
import pygame
import random
import glob
from gpiozero import Button
import time
pygame.init()
n = glob.glob('/filepath/*.wav')
btn_0 = Button(8)
btn_0.when_pressed = pygame.mixer.stop
btn_0.when.held = lambda: pygame.mixer.Sound(random.choice(n)).play()
while True:
nop
So I'm trying to make a program that randomly places my mouse in specific areas in python, and I'm still testing it so it can get a bit crazy. I was wondering if it were possible to make a fail safe command that would terminate the program if the key or command were entered.
Since the program is clicking and moving around on another window on my computer it deselects the window python is running in, which make the "Keyboard Interrupt" fail to work.
Here's the program:
import pyautogui
import random
import time
time.sleep(6)#gives you time to click the right window
try:
while True:
x = random.randint(239, 1536) #randomizes the position of the mouse
pyautogui.moveTo(x,663) #moves the mouse to position
pyautogui.doubleClick() #fires the gun in game twise
time.sleep(1) #gives time for the game to
pyautogui.doubleClick() #catch up with the mouse and fires gun
pyautogui.doubleClick() #fires gun twice again
except KeyboardInterrupt:
print ('Yup')
And if there is anything wrong with the way I'm coding please tell me. I'm still new to coding so any tips would be awesome.
PyAutoGUI also has a fail-safe feature. Moving the mouse cursor to the upper-left corner
of the screen will cause PyAutoGUI to raise the pyautogui.FailSafeException
exception.
Your program can either handle this exception with try and except statements
or let the exception crash your program. Either way, the fail-safe feature will stop the
program if you quickly move the mouse as far up and left as you can.
>>>import pyautogui
>>>pyautogui.FAILSAFE= True
By default FAILSAFE is True, and you can also disable it.
>>>pyautogui.FAILSAFE = False
What you are looking to do is use a sys.exit() in your Exception.
Try this:
import sys
try:
# all your code
except KeyboardInterrupt:
sys.exit()
this should work, whenever you click the key it will break the loop, install the module keyboard with
pip install keyboard
if keyboard.is_pressed('q'):
break
I've written a mini example for DrawingArea which, when started, displays nothing. If I insert a raw_input() just for waiting for a keyboard press at a specific place, it functions, so this is a workaround. Here's the code:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
R = 300
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_default_size(R, R)
drawing_area = gtk.DrawingArea()
window.add(drawing_area)
window.show_all()
gc = drawing_area.get_style().fg_gc[gtk.STATE_NORMAL]
if 0:
raw_input()
drawing_area.window.draw_line(gc, R/10, R/10, R*9/10, R*9/10)
raw_input()
This version doesn't display the drawn line in the opening window; upon pressing enter in the shell, it will just terminate (and remove the window). But if I enable the raw_input() at the if 0: block, it waits twice for an enter in the shell and between the two enters it will display the drawn line (so in general the code works, it seems to be just a weird refresh problem).
I also tried to flush the event queue of GTK using this snippet:
while gtk.events_pending(): # drain the event pipe
gtk.main_iteration()
I inserted it at various places, always to no avail.
I also tried the usual gtk.main() as the last command in the script (of course). But it also didn't help.
How do I do this correctly and why is that raw_input() having that strange side-effect?
You should connect to your drawing area's expose-event signal. That is the only place that you should try to draw on the drawing area; the reason for this is that anything you draw is erased again when the window is minimized or another window moves over it. However, the expose event always happens at the right time so you can keep the drawing up-to-date whenever it is needed.
Like this:
def on_drawing_area_expose(drawing_area, event, data=None):
# ... do your drawing here ...
drawing_area.connect('expose-event', on_drawing_area_expose)
Also check out drawing with Cairo, which is the preferred and more flexible way. Here is a tutorial.