why does subprocess launch an "extra" application? - python

I wrote a Python script to detect a Print Screen keypress, and launch the Snipping Tool. The script uses subprocess.call to handle the application launch.
The problem I am facing is that when I am done with Snipping Tool and close the application, I get an "extra" application being launched. For example, if I took a snip of a PowerPoint presentation, then when I close Snipping Tool I get a new / blank instance of Power Point being launched automatically. I do not want this to happen, and just want the Snipping Tool to close without any additional action.
Can someone please help explain what I am missing in my code?
# https://stackoverflow.com/questions/24072790/detect-key-press-in-python
# https://pypi.org/project/keyboard/
# https://github.com/boppreh/keyboard#api
import keyboard #pip install keyboard
import time
import subprocess
while True:
if keyboard.is_pressed('print screen'):
subprocess.call(r'SnippingTool.exe') # blocking; waits until open
keyboard.press_and_release('ctrl+N')
#elif keyboard.is_pressed('ctrl+print screen'): # not recognizing "print screen" here
elif keyboard.is_pressed('ctrl+esc'):
print 'killing it now'
break
else:
time.sleep(0.1)

I'm guessing (and I'm not on Windows), but I think that the subprocess.call waits until you have finished with Snipping Tool, and so the keyboard.press_and_release('ctrl+N') is going to PowerPoint.

Related

How do I make python wait on a "waiting" prompt within another application?

I am trying to use python to take in a string from a barcode scanner and use it to select a laser engraver file to execute. I am able to get the Max Marking (laser software) to open with the correct file, but am getting lost after that. I want to press "f2", which is the hotkey to run the laser, then wait on the "etching" prompt that the Max Marking software displays on the screen, then close Max Marking. I suppose I could test each of the engravings for their respective lengths of time and just use time.sleep(SomeAmountOfTime), but would like to make closing the program literally contingent on the engraving finishing. Is there a way to make python wait on the "currently etching" prompt that displays while the laser is running? This is within the Max Marking application and not a windows prompt. Here is what I have so far...
def notepad():
os.startfile('....filepath....')
time.sleep(2)
pyautogui.press('f2')
#Where I need to wait on etching prompt
os.system('taskkill /f /im maxmarking.exe')
A very simple solution could be _ = input("press ENTER when etching is finished"), it is not automatic but reliable.
If you want something completely automatic, it will be much more difficult. To detect that the prompt in another process has been displayed, either it provides an API to do that (which I doubt) or it will be very hacky (see the whole topic of "window automation", for exemple this question).
If having to return to the Python executing script is bothersome, you could use a hotkey to message it, see for example this question.

How to run python script after logging in?

So i've done this program that helps me to manage windows and applications that i wanna have opened after i log in , and i realized that if i put this script to startup folder it'll start the program before i even login, and that's not what i want because the program depends on the time between starting application and pressing keyboard shortcut.I need the program to start after i login.I'm using pycharm with python 3.8 . This is the code i wanna run after i Login.
import os
import time
import pyautogui
os.startfile("C:\\Program Files\\JetBrains\\PyCharm Community Edition
2019.3.2\\bin\\pycharm64.exe")
time.sleep(2)
os.startfile('C:\\Users\\Igor\\AppData\\Local\\Programs\\Opera\\launcher.exe')
time.sleep(25)
pyautogui.keyDown('ctrl')
time.sleep(0.2)
pyautogui.keyDown('win')
time.sleep(0.2)
pyautogui.keyDown('down')
time.sleep(0.5)
pyautogui.keyUp('ctrl')
time.sleep(0.1)
pyautogui.keyUp('win')
time.sleep(0.1)
pyautogui.keyUp('down')
pyautogui.press('enter')
I've already looked up the same question on stack-overflow but there was no exact answer.
Take a look at this SuperUser answer. Maybe Task Scheduler has what you're looking for?
You can adjust the trigger so that it's not every time you unlock your machine but instead only when you log on.

How to catch a process in python?

I'm currently making a lil' launcher for PortableMu while in an internship.
We (company and I) modeled a special mode for the Mu-Editor and we are shipping it with PortableMu so that users don't need to install Mu and/or Python to use it.
The problem of PortableMu for Windows is, that you start it with a .bat and this doesnt give you any feedback.
You click, you wait ~1-2min and maybe Mu-Editor will popup.
This is not very userfriendly.
So my duty is to create a launcher.
My launcher is a simple thing: Only lil "welcome" a picture and a button to start PortableMu. It works on my private windows10.
Now I want to add in randomly picked messages for simulating "loading" which shall stop when the Mu-Editor pops up. Simply to bridge the time
Is there a method to catch when this happens?
Alas:
Can Python catch the moment when Windows opens the task/process for Mu-Editor?
If, how?
use the tasklist
subprocess.Popen('tasklist').comunicate()[0] will return all the tasks currently happening in windows, simply do this every minute or so and check for your task. There are ways to make this pass without a command window popping up, here's one that i use often
command =subprocess.Popen(["ping","-n","1","-w","100", str(ip)], stdout=subprocess.PIPE, shell=False, creationflags = 0x08000000)
reply = str(command.communicate()[0])

Python time.sleep interrupted after click on terminal

I am building a command line tools using Python script. it's a loop to check data and print out some stuff after some delay seconds. It works fine until I click anything or selecting text by mouse on the terminal without keyboard event. it doesn't do anything after that, doesn't print and recheck
import time
import sys
print('some thing')
for remaining in range(10, 0, -1):
sys.stdout.write("\r")
sys.stdout.write("recheck in {:2d}.".format(remaining))
sys.stdout.flush()
time.sleep(1)
sys.stdout.write("\rComplete! \n")
input()
My environment is anaconda 64bit on windows 10
The console is blocking in the Windows SDK function WriteConsole because the console window is in a mode called QuickEdit mode.
To fix the issue, go to the properties option in the upper left corner menu of the console.
Then uncheck QuickEdit mode.
QuickEdit mode is there to help with copying and pasting text from the console. So when the console is in that mode, it stops all writing to the console so that the text isn't moving while you are trying to select and copy/paste.
Python significantly changed its system signal handling in Python 3.5. https://www.python.org/dev/peps/pep-0475/
It used to throw an InterruptedError whenever a signal interrupted a system call. Now the system call wrapper code upon signal interruption will recall the system call recalculating any timeouts if necessary. A bug at this level could recall the system call with an absurdly long value.
Attach a debugger and see where the process is at when it is stuck.
EDIT: after attaching windbg to stuck console. I discovered that this isn't the problem. I posted the real solution in a new answer.

GUI program with toggable console?

I've seen some apps allow you to show/hide the console when you need to read log messages. For example Blender3D allows that (blender.org).
I was wondering if this can be done in Python and how.
My main window is a Panda3D (panda3d.org) window.
I've read somewhere that one option is to hide the "real" console (pythonw) and create another console and just redirect everything from the "real" one to it, every time you want to "show" the "real" console. No idea how this can be done.
Or at least a way to choose whether to start the program with the console or without it by reading a configuration file or something.
I'm assuming you are talking about Windows because this console toggling in blender is Windows exclusive. I'm guessing Blender uses GetConsoleWindow and ShowWindow on Windows.
This is how you could do it in python with pywin32:
import win32gui, win32console, win32api, win32con
import time
console_window = win32console.GetConsoleWindow()
time.sleep(1)
win32gui.ShowWindow(console_window, win32con.SW_HIDE)
time.sleep(1)
win32gui.ShowWindow(console_window, win32con.SW_SHOW)
time.sleep(1)
If you run this program with python and not pythonw it will show the console, sleep for a second, hide the console, sleep for another second and then hide it again.
Mind that this code only works on Windows. On other platforms silly stuff like this is not necessary because if you want a program to show a console then you run it from the console.

Categories