Python: catching error + printing to file - python

I wonder if there is a way to capture any (and all) type of error that crashes the script, but potentially without using try to catch a specific exception.
I have a webdriver script that does a lot of stuff, like clicks on links, sends keys and so on, but I cannot predict where it will crash. I want to run a series of tests in sequence and print results into a file - including any errors/crashes:
Eg.
Test01 - Success!
Test02 - NameError: name 'driver' is not defined !ERROR!
Test03 - Success!
and so on.
So that at the end I can just open the text file and check which tests need to be fixed and re-run.
Now I've been using try/exception with smaller blocks of code, but it seems to me that I would have to somehow include the whole script within try/catch/exception to get what I want.
Is there a better way to catch any type of error that is displayed after a script crashes, like on the image below:

You can use a plain except to catch any and all exceptions, like so:
try:
some code here
except:
print 'whoops, something went wrong'
However this doesn't give you any information about the exception, so you probably don't want to do that.
You can also catch the very broad Exception, like so:
try:
some code here
except Exception as ex:
print 'oops, caught this error: %s' % ex
This is a better method as it tells you what exactly went wrong.

It seems the trick you are looking for is redirecting the stderr to a file or stdout.
Python when having the exception will write the exception to stderr .
simply you need to redirect stderr to the same output file you have when running the python program
like this
python file.py &> outputfile

Related

how do I prevent python exe from closing when an error occurs

try:
some code here
except Exception as e:
print("error: ",e)
here if this python exe code produces an exception it immediately closes the exe terminal
how do I stop it from exiting the exe terminal so that I can understand what exception exactly occurred
also I cant run it in CMD I have to run the exe file only
also I cant use the press any key method
The terminal closes when the program terminates. When you catch the exception, you print your error message, and then the program terminate, so you don't really gain much from catching the exception; in fact, you even get less (you don't print the stack trace).
To get the stacktrace, look into traceback:
try:
foo = 123 / 0
except Exception as e:
traceback.print_exception(e)
Then you need to have the program wait a bit that you can actually see the stack trace and error you print. A simple way is to just wait for input:
try:
foo = 123 / 0
except Exception as e:
traceback.print_exception(e)
wait_for_it = input('Press enter to close the terminal window')
Or you could add a break point to have the Python debugger pdb come up. (It does at least on Mac OS when I run this code in a terminal, no idea about Windows.) See the above link for help on it, or type help at its prompt.
try:
foo = 123 / 0
except Exception as e:
breakpoint()
Speaking of terminal: if you just open a command prompt or bash terminal, you can just run your code with python3 myprog.py and that terminal does not automatically close, so that you can see the output without modifying the program. Depending on how you run your code and what module dependencies you have, this may need a bit more setup (like a virtual environment) but is probably worth it in the long run.

subprocess.check_output in try/except runs and then throws exception

I am using the following in a script:
try:
subprocess.check_output(file_path,shell=True)
except:
print("Error: Unable to open file.")
This code works mostly as intended with the only problem being that it still throws an exception on successful operations.
I will be using this with Tkinter to display message boxes and don't want my users to receive an error every time they close their successfully opened file. I am a bit of a novice and don't understand the subprocesses as well as I'd like to. I was originally using .Popen but from what I read, check_output is the best way to catch the exception.
Is there something I am missing or an easy way to fix this?
Edit: I checked the error via this method:
try:
subprocess.check_output(file_path, shell=True)
except subprocess.CalledProcessError as e:
print(e.output)
it just returns
b''
When I add print(e), I get this:
Command '<file_path>' returned non-zero exit status 1.
where the <file_path> is the actual path to the file.
I've also tried using .Popen and then .communicate() to view the output and error, but both return none whether-or-not .Popen has a target. If there is no target, I also see this in cmd:
<file_path> is not recognized as an internal or external command,
operable program or batch file.
Basically, I just want to throw an error if the target file path is not valid. If it is valid, I want it to open the file. I don't need to know the error, just that the file doesn't exist.

How do I stop AssertionError messages from subprocess.check_call() in unittest

I have a test that is calling a script using subprocess.check_call. I have assertions inside the script checking the validity of the arguments and I want to check the error cases. So I've done this:
try:
self.assertRaises(subprocess.CalledProcessError, subprocess.check_call, ['myscript.py', 'myBadArgument'])
except AssertionError:
pass
The test actually passes since the correct assertion gets raised, but I want to keep the assertion messages and associated stack dump from getting printed to the screen.
How do I do this?
Thanks!
To suppress the subprocess's error messages, redirect its stderr:
from subprocess import DEVNULL
with self.assertRaises(subprocess.CalledProcessError):
subprocess.run(['myscript.py', 'myBadArgument'], stdout=DEVNULL, stderr=DEVNULL)
Also, don't catch AssertionError. That doesn't do anything to suppress the subprocess's error messages; it only causes your test to incorrectly pass even if the subprocess doesn't raise an error.
The problem here was that I was overusing the assert() statement. I was using assert to check for things such as whether the user gave me files that existed, or values that made sense in the script.
This was a misunderstanding on my part. I now see that the correct approach is to check the data and raise the appropriate exceptions in my library elements, then catch those exceptions in my user-facing scripts and provide a call-stack free message.
Once I cleaned this up my test passed with the correct exceptions and with no unneeded messages.

How to catch exception from a system() command in python

I have a system() command and I want to catch the exception it may generate. The code that I have is:
def test():
filename = "test.txt"
try:
cmd = "cp /Users/user1/Desktop/Test_Folder/"+filename+" /Users/user1/Desktop/"
output = system(cmd)
except:
print 'In the except'
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
test()
When I execute the above code and say the file that I want to copy is not present then the error is not caught and the code does not enter the except section. How can I catch such errors generated by system() commands?
Note: The above system() command is just an example. There are multiple such system() commands and each of them vary from one another
The system() command doesn't throw an exception on failure; it will simply return the exit status code of the application. If you want an exception thrown on failure, use subprocess.check_call, instead. (And, in general, using the subprocess module is superior in that it gives you greater control over the invocation as well as the ability to redirect the subprocess's standard input/output).
Note, though, that if most of the operations you are doing are simple filesystem operations like copying files from one location to another, that there are Python functions that do the equivalent. For example, shutil provides the ability to copy files from one location to another. Where there are Python functions to do the task, it is generally better to use those rather than invoke a sub process to do it (especially since the Python-provided methods may be able to do it more efficiently without forking a process, and the Python versions will also be more robust to cross-platform considerations).

Stop Windows from closing Python

This question may have been asked a couple of times but I cannot seem to find it.
Basically I am just learning Python and I am on Windows, this means I double click the .py file and open it. This works great until an error appears, at which point Python calls exit and the window closes.
One way, of course, to get around this is to use the cmd program in Windows and run the Python program from there, however, is there a way to fix it so that my application doesn't bail out and close as soon as it hits an error if I open it from Windows Explorer?
while(True):
try:
number = input('Enter a number: ')
if(is_int(number) is False):
print('Please actually enter a number')
if(number > 0):
answer = input('Oh Noes you really want that?')
if(answer == 'yes'):
sys.exit(0);
except KeyboardInterrupt:
sys.exit(0)
except Exception as e:
input('')
In order to keep your program intact, e.g. to not introduce unwanted catch-em-all exception handling (aka pokemon handling) there are at least three options:
Use any console terminal, e.g. built-in cmd or powershell or any third-party console apps out there.
Use any IDE: pycharm, IDLE (python windows installer by default sets it up) or whatever you have capable of running python code.
Use text editor plugins for running python code. At least notepad++ and sublime text are capable of doing so.
I would recommend starting with option 1 for starters, then slowly move to option 3 for small scripts and projects, and option two for larger ones.
I you put an input function at the bottom of your script then it will hang there until you hit enter or close the command prompt. If you call an exit function put it immediately before the exit function is called. Otherwise place it at the bottom of the script.
Also I assume you have defined is_int already in your script?
What would you think it should do?
Python is drawing the window you see, if python crashes, the windows is going away.
You can run it trough cmd, or within an IDE. (like IDLE, that has some problem though when it comes to GUI)
Otherwise, add something like this at the end of the file
try:
run()
except Exception as inst:
print type(inst), inst.args
#it prints the exception
print sys.exc_traceback.tb_lineno
#if you want the line number where the error occurred in the source code
raw_input()
inst is the exception instance, you can see the type and the list of arguments.
Then with the sys module you can also see the line where the error occurred in the code.
This way every error will be handled and displayed before closing
Is this the right way?
No. You should really be using ad IDE (like Eclipse with PyDev or PyCharm).
After #SeçkinSavaşçı's extremely useful comment at the start:
The most common way is to let it wait for an input, then ignore the input and terminate the script.
Which took me a second to understand I went in search of how to do this, so first I saw to stop the script and used:
while(True):
try:
# Application code here
except:
input('')
Which worked really well to catch all errors, which unlike in PHP (which I have become comfortable with unfortunately) are all exceptions.
So the next part was to to tell me what error had occured and how to fix it, I needed a backtrace. It just so happens that the Python docs gave me the answer right here: http://docs.python.org/2/library/traceback.html#traceback-examples in an easy to see example:
exc_type, exc_value, exc_traceback = sys.exc_info()
print(traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout));
Add that above the input('') and I had my perfect error handling showing me everything I needed.
Thanks all,
Try import time and time.sleep(). Also, I recommend you to use IDLE or Geany. I've been using them and they work out well.

Categories