Python 3 - error handling in a GUI app - python

So I'm making my first 'real' application but I want to know how to handle exceptions when I build my python script into an executable (.exe, Windows only). If I do normal try/except clauses, how should I record an error? I don't believe print functions would do anything, so does that just leave making some sort of log file?

Either it's a CLI application and you can use the print function (preferably using stderr). Or it's a window application and you can use some pop-up windows to announce the error to the user. Logs are of course applicable to both cases.
EDIT:
For pop-up in Windows you can use something like this:
import ctypes
ctypes.windll.user32.MessageBoxA(0, "Message", "Title", 1)

Related

Python - control application started by the different user in Windows

I am making application that controls a browser with SendKeys. But as SendKeys get the full control over the keyboard, I want to run this app under the different user. This way I will be working, the application will do what it have to do, and we will not make problems for each other).
The simplest code is
import time
import SendKeys
time.sleep(10)
SendKeys.SendKeys('hello')
I run it, focus on the field where I want to insert my text "hello", and wait. If I don't change the user, all is done as expected.
But when I run it, change the user and return after 10 seconds, I see that SendKeys sent nothing to the program.
How to send keystrokes to the program under the different user?
(I was trying to do the same with pywinauto, but the result was almost the same - all is good if I don't change the user, and error if I change it. So I thought that it is much simplier to resolve this problem with only SendKeys).
Just to summarize our discussion in comments and in the chat. Your wishes are very wide. I'm just trying to show you some directions to learn.
If you want to use SendKeys/TypeKeys/ClickInput methods (working as a real user), you need to run your automation script in the remote session, not locally. This is explained in details in my other answer: SetCursorPos fail with "the parameter is incorrect" after rdp session terminated.
If you want to run the automation on the same machine silently (in minimized state), there is an example for dealing with hidden windows: Python - Control window with pywinauto while the window is minimized or hidden. Just minimize the window and use silent methods (almost all except ClickInput and TypeKeys).
Feel free to ask more detailed questions about pywinauto and GUI automation.

is it possible to launch a window that does not stop the mainloop in python

OS = windows 7
I have a python program (works) that is listening to activity on the usb bus. I want to perform a lot of tests that require a particular user input at a particular time. I would like to pop up a window that says, "press button xxx". The key point is that the mainloop needs to continue running because it's looking for events. I don't care about the window or if it remains or not and I don't need to capture any information from the window. I just want a message to the user to press the correct button at the correct time. Any type of signaling would work; it doesn't have to be a gui window. It doesn't have to look pretty. Appreciate any suggestions or links to something like this. thx
It sounds like the operation of the Python script you're running does not depend upon the user input you request. To run another process without interrupting the Python script execution you can use:
import subprocess
subprocess.Popen([exe,arg1,arg2,arg3])
where
exe = executable/script to run from your OS command line
arg1= first argument to pass to exe
arg2= second argument to pass to exe
etc... (as many arguments as your OS supports in a list)
This separate exe process could request input from the user.

Robustly killing Windows programs stuck reporting 'problems'

I am looking for a means to kill a Windows exe program that, when being tested from a python script, crashes and presents a dialog to the user; as this program is invoked many times, and may crash repeatedly, this is not suitable.
The problem dialog is the standard reporting of a Windows error:
"Foo.exe has encountered a problem and needs to close. We are sorry for the inconvenience"
and offers a Debug, Send Error Report, and Don't Send buttons.
I am able to kill other forms of dialog resulting from crashes (e.g. a Debug build's assert failure dialog is OK.)
I have tried taskkill.exe, pskill, and the terminate() function on the Popen object from the subprocess module that was used to invoke the .exe
Has anyone encountered this specific issue, and found a resolution?
I expect automating user input to select the window, and press the "Don't Send" button is one possible solution, but I would like something far simpler if possible
Wouldn't it be easier to disable the error reporting feature?
If you were to use CreateProcessEx or a WinAPI specific function, you might be able to call TerminateProcess or TerminateThread to forcibly end the process.

When using py2app, is there a way to customize the traceback dialog that gets displayed? (Or show a different Cocoa dialog?)

Is there an easy way to get any more control over the py2app traceback dialogs, or just a nice way to display GUI messages?
If I raise an exception in my py2app script, I get a dialog that says something like this:
MyAppName Error
MyAppName Error
An unexpected error has occurred during execution of the main script
MyRaisedError: This is the text that I can control when I raise the error.
It has Open Console and Terminate buttons. My script needs to check if a certain DVD is in the drive, if it's not, I want to show an error dialog and quit. I would like to have more control over it than this, as I can only change some of the text and can't control the buttons.
I tried calling osascript to do 'display dialog' via applescript, but it gave me an error like this: 0:19: execution error: No user interaction allowed. (-1713) I don't particularly like this way of doing it, but if it's all I can do...
I would really prefer not to include a big project like Cocoa Dialogs or something like a PyObjC project... the script itself is very tiny and I can't see adding 10x the meat of my script just to get the dialog.
Instead of using osascript, you can call display dialog via py-appscript which, if you don't already have it in your python site-library, can be installed via easy_install. This example works inside of a py2app-generated app:
#!/usr/bin/env python
from osax import *
import py2app
def doit():
sa = OSAX()
sa.display_dialog("Python says hello!",
buttons=["Hi!", "Howdy!", "Duuuude!"],
default_button=3)
if __name__ == '__main__':
doit()
Just put a standard Python try/catch block around the section of code that throws the exception, then use NSAlert to tell your users they need to put the DVD in

Detect windows logout in Python

How can I detect, or be notified, when windows is logging out in python?
Edit:
Martin v. Löwis' answer is good, and works for a full logout but it does not work for a 'fast user switching' event like pressing win+L which is what I really need it for.
Edit: im not using a gui this is running as a service
You can detect fast user switching events using the Terminal Services API, which you can access from Python using the win32ts module from pywin32. In a GUI application, call WTSRegisterSessionNotification to receive notification messages, WTSUnRegisterSessionNotification to stop receiving notifications, and handle the WM_WTSSESSION_CHANGE message in your window procedure.
If you're writing a Windows service in Python, use the RegisterServiceCtrlHandlerEx function to detect fast user switching events. This is available in the pywin32 library as the RegisterServiceCtrlHandler function in the servicemanager module. In your handler function, look for the SERVICE_CONTROL_SESSIONCHANGE notification. See also the WM_WTSSESSION_CHANGE documentation for details of the specific notification codes.
There's some more detail in this thread from the python-win32 mailing list, which may be useful.
I hope this helps!
In a console application, you can use win32api.SetConsoleCtrlHandler and look for CTRL_LOGOFF_EVENT. In a GUI application, you need a window open and wait for the WM_QUERYENDSESSION message. How precisely that works (and if it works at all) depends on your GUI library.

Categories

Resources