Why does my if in a loop make a beep - python

I'm using pyautogui to click on a button that periodically pops up on my GUI as shown in the script below. However when the button is not on the screen, the script makes two annoying beep sounds while going through the loop.
If I replace pyautogui.locateOnScreen(...) with None, which seems to be the return value if the image can't be located on the screen, the sound seems to disappear.
The script runs in a Jupyter Notebook (v4) using python 2.7 and I'm on Debian 8.1 with Gnome.
import pyautogui
import time
starttime = time.time()
while time.time()-starttime<10:
img_path_inactive = "/home/user/folder/inactive_target.png"
img_path_active = "/home/user/folder/active_target.png"
img_list = [img_path_inactive, img_path_active]
get_target = map(pyautogui.locateOnScreen, img_list) # <--- This line beeps! See edit 2
if any(get_target):
pyautogui.click(filter(None, get_target)[0][0], filter(None, get_target)[0][1])
# The if check above was previously (hence the title):
# if pyautogui.locateOnScreen(img_path_active) or pyautogui.locateOnScreen(img_path_inactive):
# click_target = pyautogui.locateOnScreen(img_path_active) or pyautogui.locateOnScreen(img_path_inactive)
# pyautogui.click(click_target[0], click_target[1])
time.sleep(2)
print("Finished loop.")
Edit
I put the script in a .py file and ran it from the command line to check if it is a jupyter thing. It still beeped though.
Afterwards I ran pyautogui.locateOnScreen against three images, which caused predictably three beeps... So it definitely seems to be a pyautogui issue/'feature'...
Edit 2
pyautogui.locateOnScreen is imported from here, see line 238. It actually does seem to raise an exception:
except ImageNotFoundException:
if time.time() - start > minSearchTime:
raise

I'm also on GNU/Linux and experiencing beeping when the pyautogui.locateOnScreen() function runs (whether or not it locates the image).
I found that scrot is the culprit. The solution:
$ sudo mv /usr/bin/scrot /usr/bin/scrot-noisy
Create /usr/bin/scrot with these contents:
#!/bin/bash
scrot-noisy --silent "$#"
$ sudo chmod a+x /usr/bin/scrot

Ok, I found a workaround to the beeping.
After going to the source of the module from which pyautogui.locateOnScreen is imported, I believe that the function raises a custom ImageNotFoundException somewhere down the track. I didn't fully debug it though.
Being on Gnome, all Exceptions are announced by an annoying beep.
The workaround that did it for me was to turn off the system beep altogether.
I added the following line to ~/.xsession:
xset b off
which killed the beep.

Related

Is there a way to directly tell my python program to use the mouse with os.system("import filename.png")?

I've been trying to write a little screenshot script for arch. It works, but the problem is when I try to assign it a keybinding in my i3-config it does nothing.
First I tried writing it fully in bash which worked fine but I stumbled onto the same problem with it not executing.
So I have redirected the output to a log-file to check it out and it welcomes me with this:
import: unable to grab mouse '': Datei oder Verzeichnis nicht gefunden # error/xwindow.c/XSelectWindow/9306.
import: unable to read X window image '': Erfolg # error/xwindow.c/XImportImage/4942.
import: unable to read X window image '': Erfolg # error/xwindow.c/XImportImage/5049.
import: `/home/lukas/Screenshot/20190419/scoot7.png' # error/import.c/ImportImageCommand/1288.
Translation first line: Couldn't find file or directory # error[...]
Translation Erfolg: success
I've tried googling it, which didn't lead me to anything really and I didn't really find any path resembling error/xwindow.c and so on.
Here is my code:
#!/usr/bin/env python
import os, os.path
import datetime
import sys
d = datetime.datetime.today()
directory="/home/lukas/Screenshot/%s"%d.strftime('%Y%m%d')
if not os.path.exists(directory):
os.mkdir(directory)
fileCount = 1
for file in os.listdir(directory):
if file.endswith('.png'):
fileCount+=1
filename = "%s/scr%d.png"%(directory,fileCount)
os.system("import %s"%filename)
and here is my entry to my i3 config:
bindsym $mod+Shift+F12 exec --no-startup-id scoot > /tmp/log.out 2>&1
The expected outcome of this is that when I press mod+shift+f12 it should transform my mouse-pointer to a "crosshair" so I can select something and takes a screenshot of that.
The actual result is that if I run it normaly it works, but if I try to use the Keyboard-Shortcut it just does nothing but output to my logfile.
I am pretty much a newbie to programming and linux, and I have no idea why it cannot find my mouse and I wanted to know if I can explicitly tell the program to use it or if there is another way to do this.
Thanks alot.
Hugenotte
I wrote a bash script a little while ago to do exactly what you are trying to do, using the very common utility ImageMagick that you can find here on Arch.
Here it is in case you are open to this alternative:
#!/bin/bash
# take screenshot using import from imagemagick
# allows to select the area by dragging across a rectangle
# or to select entire window by clicking inside it
set -e
# the date and time will be used as the file name
time=$(date +"%F_%H:%M:%S")
# naming the urxvt window "screenshot" so that the i3 "no_focus" option gets applied to it
urxvt -title "screenshot" -e bash -c "import $HOME/Screenshot/$time.png"
I then use it in i3 with:
no_focus [title="screenshot"]
bindsym $mod+Shift+F12 layout tabbed; exec --no-startup-id bash my_script.sh
Of course, you may want to change the date format to what you had in python. I like having the time in case I take several screenshots in a row. And you have to replace urxvt with the name of your terminal emulator and you might have to adapt the -title flag if your terminal emulator doesn't give windows a name in this way.
Note that naming the window is important: it took me a little while to figure out how to go around what happens without naming the window and using the no_focus on that window in i3:
The focus would jump to the screen capture window and thus out of the window of which I wanted to take a screenshot. It might be possible that the issue you are facing with your bash and python scripts may be related to this. You have to force i3 to keep your mouse on the old window and not jump to the screen capture window triggered by the script (by default, i3 will focus on a newly created window).

Run .py file until specified line number

In a linux terminal typing
python script.py
Will run run script.py and exit the python console, but what if I just want to run a part of the script and leave the console open? For example, run script.py until line 15 and leave the console open for further scripting. How would I do this?
Let's say it's possible, then with the console still open and script.py run until line 15, can I then from inside the console call line fragments from other py files?
...something like
python script.py 15 #(opens script and runs lines 1-15 and leaves console open)
Then having the console open, I would like to run lines 25-42 from anotherscript.py
>15 lines of python code run from script.py
> run('anotherscript.py', lines = 25-42)
> print "I'm so happy the console is still open so I can script some more")
I'm so happy the console is still open so I can script some more
>
Your best bet might be pdb, the Python debugger. You can start you script under pdb, set a breakpoint on line 15, and then run your script.
python -m pdb script.py
b 15 # <-- Set breakpoint on line 15
c # "continue" -> run your program
# will break on line 15
You can then inspect your variables and call functions. Since Python 3.2, you can also use the interact command inside pdb to get a regular Python shell at the current execution point!
If that fits your bill and you also like IPython, you can check out IPdb, which is a bit nicer than normal pdb, and drops you into an IPython shell with interact.
if you want to run script.py from line a to line b, simply use this bash snippet:
cat script.py|head -{a+b}|tail -{b-a}|python -i
replace {a+b} and {b-a} with their values
You could use the python -i option to leave the console open at the end of the script.
It lets your script run until it exits, and you can then examine variables, call any function and any Python code, including importing and using other modules.
Of course your script needs to exit first, either at the end or, if your goal is to debug that part of the script, you could add a sys.exit() or os._exit() call where you want it to stop (such as your line 15).
For instance:
import os
print "Script starting"
a=1
def f(x):
return x
print "Exiting on line 8"
os._exit(0) # to avoid the standard SystemExit exception
print "Code continuing"
Usage example:
python -i test_exit.py
Scrit starting
Exiting on line 8
>>> print a
1
>>> f(4)
4
>>>
You cannot do that directly but you can do something similar from inside Python console (or IDLE) with exec :
just open you favorite Python console
load wanted lines into a string and exec them :
script = 'script.py'
txt = ''
with open(script) as sc:
for i, line in enumerate(sc):
if i >= begline and i<= endline:
txt = txt + line
exec(txt)
You can even write your own partial script runner based on that code ...
EDIT
I must admit that above answer alone really deserved to be downvoted. It is technically correct and probably the one that most closely meet what you asked for. But I should have warned you that it is bad pratice. Relying on line numbers to load pieces of source files is error prone and you should avoid it unless you really know what you are doing and why you do it that way. Python debugger at least allows you to control what are the lines you are about to execute.
If you really have to use this solution be sure to always print and double check the lines that you are about to execute. IMHO it is always both simpler and safer to copy and past lines in an IDE like IDLE that is packaged into any standard Python installation.

IDLE subprocess startup error

I have the code below in a file called code.py. I am using IDLE to edit the file. When I click Run>Run Module I get the error:
"IDLE's subprocess didn't make connection. Either IDLE can't start a
subprocess of personal firewall software is blocking the connection."
I am using Windows 7 Ultimate 64bit, but I have the 32bit version of Python 2.7 installed.
I have looked for a solution on this site as well as others but all of them seem to recommend deleting something called tkinter.py (I have no idea what this is) or to turn off my firewalls (I have none enabled aside from Microsoft Security Essentials which isn't a firewall.)
#Globals
#-------------------
x_pad = 476
y_pad = 444
import ImageGrab
import os
import time
import win32api, win32con
def screenGrab():
box = (x_pad+1,y_pad+1,x_pad+641,y_pad+480)
im = ImageGrab.grab(box)
im.save(os.getcwd() + '\\full_snap__' + str(int(time.time())) +
'.png', 'PNG')
def main():
pass
if __name__ == '__main__':
main()
def leftClick():
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
time.sleep(.1)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
print 'Click.' #completely optional. But nice for debugging purposes.
def leftDown():
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
time.sleep(.1)
print 'left Down'
def leftUp():
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
time.sleep(.1)
print 'left release'
def mousePos(cord):
win32api.SetCursorPos((x_pad + cord[0], y_pad + cord[1])
def get_cords():
x,y = win32api.GetCursorPos()
x = x - x_pad
y = y - y_pad
print x,y
The thing is "python.exe" is being obstructed by "tkinter.py") that you created(i.e., you have written a program with Tk() and named it as tkinter.py and saved that in the root folder of python). And that's it just make sure that you don't save any program file directly in the root folder of python.
Another fix!!! Hopefully this will help someone.
I had the same problem and noticed something quite interesting. I had accidentally named a file (inside the desktop folder I was working in) "tkinter" (it will cause the same problem if you rename a file by any reserved keyword, I assume). Everytime I ran or attempted to run this file, it created a pycache folder, and the error you mention above came up. Deleting the erroneously named python file solved the problem.
So - look for ANY files (in the folder you are working with or indeed the root folder) that are named after any reserved words. Delete them. Hopefully it'll work!
I had the same problem. what i did that solved it, was to move every .py file that i had created in "C:\Python33" folder, to a sub-folder that i named "Examples". seems like one of my files was the cause of this problem.
I also had the following problem. My file was named code.py, and was working fine untill I installed Canopy, and numpy.
I tried reinstalling python, but what solved the problem for me was simply renaming the file. I called my file myCode.py, everything started working fine. Strange problem...
I made a python file and named it "socket.py" so then python IDLE showing an error on startup that 'startup failure'
so the problem is that if we are using python reserved keywords or module names as our python file name that it conflicts with built-in modules.
the solution is: go to path C:\Users\sony\AppData\Local\Programs\Python\Python38 where your python files are saved and just renamed that file.
then start IDLE.
Happily using IDLE continously under python36 and windows10, it has suddenly given this error on all the programs I'm working on, with no new files created.
I terminated IDLE and tried to restart it with idle.bat but that no longer works.
Happily I have been able to restart it successfully with Lib\idlelib\idle.pyw.
All my recent programs are there and they can again be run without problems.
No need to reinstall python.

Crontab camera capture using python-opencv

Here is my python program:
#!/usr/bin/env/ python
import cv
capture1=cv.CaptureFromCAM(0)
cv.SetCaptureProperty(capture1,cv.CV_CAP_PROPER_FRAME_WIDTH,320)
cv.SetCaptureProperty(capture1,cv.CV_CAP_PROPER_FRAME_HEIGHT,240)
while 1:
cam1=cv.QueryFrame(capture1);
cv.SaveImage("camera.jpg",cam1);
cv.WaitKey(11)
print 'Done!'
On crontab:
#reboot sudo python /home/program.py >/home/result.txt
But its not saving the image.Definitely I have done something wrong! I got the similar problem when I was reading image cv2.imread("image.jpg") but it was returning None so I added full path to the image /home/image.jpg.That problem was solved!.Is cron not getting camera feed?
Thanx for help!
First and foremost, make sure the application succeeds communicating with the camera:
import cv
capture1 = cv.CaptureFromCAM(0)
if not capture1 :
print "!!! Failed to open a camera interface"
# Ideally, exit the application.
cv.SetCaptureProperty(capture1,cv.CV_CAP_PROPER_FRAME_WIDTH,320)
cv.SetCaptureProperty(capture1,cv.CV_CAP_PROPER_FRAME_HEIGHT,240)
Remember to test if the frame was successfully retrieved from the camera:
while 1:
frame = cv.QueryFrame(capture1);
if not frame:
print "!!! Failed to retrieve frame"
break
# Right now, your code overwrites the same file at every iteration of the loop.
# It might be better to add a BREAK at the end for testing purposes.
cv.SaveImage("camera.jpg", frame);
# There's no need to call WaitKey() if the image is not displayed on a window.
#cv.WaitKey(11)
print 'Done!'
SaveImage() will fail when the application doesn't have permission to write files in the directory from where it was executed. Since crontab is responsible to call your application, I imagine that it does that from a directory where the user doesn't have the right permissions. If this is the case, I strongly suggest you to feed SaveImage() with the full path to the file.
The problem was in cv.ShowImage or cv2.imshow.When I commented this line everything worked fine! Previously the program got stuck at this this line.(while execution through cron).[That I was writing in my original program]

Is there an interpreter for Python similar to Pry for Ruby? [duplicate]

Is there a way to programmatically force a Python script to drop into a REPL at an arbitrary point in its execution, even if the script was launched from the command line?
I'm writing a quick and dirty plotting program, which I want to read data from stdin or a file, plot it, and then drop into the REPL to allow for the plot to be customized.
I frequently use this:
def interact():
import code
code.InteractiveConsole(locals=globals()).interact()
You could try using the interactive option for python:
python -i program.py
This will execute the code in program.py, then go to the REPL. Anything you define or import in the top level of program.py will be available.
Here's how you should do it (IPython > v0.11):
import IPython
IPython.embed()
For IPython <= v0.11:
from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed()
ipshell() # this call anywhere in your program will start IPython
You should use IPython, the Cadillac of Python REPLs. See http://ipython.org/ipython-doc/stable/interactive/reference.html#embedding-ipython
From the documentation:
It can also be useful in scientific
computing situations where it is
common to need to do some automatic,
computationally intensive part and
then stop to look at data, plots, etc.
Opening an IPython instance will give
you full access to your data and
functions, and you can resume program
execution once you are done with the
interactive part (perhaps to stop
again later, as many times as needed).
You can launch the debugger:
import pdb;pdb.set_trace()
Not sure what you want the REPL for, but the debugger is very similar.
To get use of iPython and functionality of debugger you should use ipdb,
You can use it in the same way as pdb, with the addition of :
import ipdb
ipdb.set_trace()
I just did this in one of my own scripts (it runs inside an automation framework that is a huge PITA to instrument):
x = 0 # exit loop counter
while x == 0:
user_input = raw_input("Please enter a command, or press q to quit: ")
if user_input[0] == "q":
x = 1
else:
try:
print eval(user_input)
except:
print "I can't do that, Dave."
continue
Just place this wherever you want a breakpoint, and you can check the state using the same syntax as the python interpreter (although it doesn't seem to let you do module imports).
It's not very elegant, but it doesn't require any other setup.
Great answers above, but if you would like this functionality in your IDE. Using Visual Studio Code (v1.5.*) with Python Setup:
Highlight the lines you would like to run and
right click and select Run Selection/Line in Interactive Window from the drop down.
Press shift + enter on your keyboard.
Right click on the Python file you want to execute in the file explorer and select Run Current File in Interactive Window
This will launch an interactive session, with linting, code completion and syntax highlighting:
Enter the code you would like to evaluate, and hit shift + enter on your keyboard to execute.
Enjoy Python!

Categories

Resources