Can Syntax Errors be handled? - python

Consider the following code:
try:
if True a = 1 #It's missing a colon So it's a SyntaxError!!!!!!!
except SyntaxError:
print 'hey'
You'd expect it to print hey However It raises a SyntaxError, The same error I'm trying to avoid. So Can all Exceptions be handled using a try-except block? Well If SyntaxError's were an exception why is it included in the built-in exceptions? and finally how can I fix the above piece of code so that it handles the exception properly?
Note: I know what I'm trying to do Is utterly pointless and serves no real purpose

SyntaxError is a perfectly ordinary built-in exception. It is not special in any way. Only the circumstances of when it's (usually) thrown are a bit unusual.
A syntax error means that the code featuring said error cannot be parsed. It doesn't even begin to be a valid program, hence it cannot be executed. Therefore SyntaxError exceptions are raised before the program is run, and hence can't be caught from within the program.
More specifically, this exception is raised by the parser. Because the parser runs fully before the code is executed, rather then interleaved with it, a program can't catch its own syntax errors.
The parser itself is just another program though: Code invoking the parser can catch SyntaxErrors like every other exception (because it is like every other exception). Examples of "invoking the parser" include:
compile, exec, eval
import statements
Several functions in modules like ast, tokenizer, parser, etc.

Of course you need SyntaxError as a built-in exception - what else should be raised if the compiler/parser encounters a syntax error?
You're right that this error usually happens at compile time, which is before you're able to catch it (runtime). (And how would you recover from it?)
I can think of one exception, though:
>>> try:
... eval("hello =")
... except SyntaxError:
... print("Hey! Who's using eval() anyway??")
...
Hey! Who's using eval() anyway??

Related

How can I throw an error in ply-yacc inside a special parse function?

I am working with library ply to make a parser for commands. Code is
def p_expr(v):
'expr : token'
... # action with token, set expr value and return
??? raise error ??? # yacc must stop parse and call p_error
def p_error(p):
print('Error!')
How to raise error?
Note that Ply does not "stop the parse" when a syntax error is encountered. It tries to do error recovery, if the grammar was built with error recovery, and as a last resort it restarts the parse as though the input had been deleted up to that point. To see this, try typing 1+2 error 3+4 into the calculator example in the Ply distribution. It will print an error message for error (because it's expecting an operator) and then restart the parse, so that it prints 7.
If you want the parser to stop when it finds an error, you'll need to raise an exception from p_error. It's generally best to define your own exception class for this sort of thing. Avoid the use of SyntaxError because Ply handles that specially in certain cases, as we'll see below.
Usually, just stopping the parser is not really what you want to do -- if you don't want to try error recovery, you should normally at least do something like throw away the rest of the input line before restarting the parse.
If you do just want to stop the parser and you raise an exception in p_error to accomplish that, then the best way to signal your own error from a parser action is to call p_error with the current token.
If you want to trigger Ply's normal error recovery procedure, you an raise SyntaxError from a parser action. However, as the manual indicates, this does not call p_error, so you'll have to do that yourself before raising the error.
If you do panic mode recovery in p_error, then you're might be out-of-luck with custom error detection. Raising SyntaxError by-passes the call p_error; while you are free to call p_error yourself, there is no mechanism to pass a new token back to the parser. (Panic mode recovery is not an optimal error recovery technique, and it is not always necessary to return a replacement token. So this paragraph might not apply.)

Why isn't my code excepting the errors?

I have this little piece of code I wrote that isn't excepting the errors that could be thrown at it. Here's the code:
def println(stringint):
try:
print stringint
except (SyntaxError, NameError):
print "Invalid format."
I run the code from the python interpreter like this, and only like this:
>>> import pcl
>>> pcl.println("Hello")
Why aren't the errors being excepted? How can I catch the errors?
Those errors that has to do with syntax are parse level errors, which means, that are errors that take place before that particular code being interpreted.
The following arenĀ“t the same type of errors:
print("Hello) # Note the missing '"'
that
print(4/0) # Syntactically correct, but obviously an error.
Hence, syntax error can't be handled by the try -- except block.
See this answer for more detail: SyntaxError inconsistency in Python?
Your code works fine, "Hello" should raise neither an EOLError nor a NameError, because the quotes are closed, and it is a string.

Ignore exceptions thrown and caught inside a library

The Python standard library and other libraries I use (e.g. PyQt) sometimes use exceptions for non-error conditions. Look at the following except of the function os.get_exec_path(). It uses multiple try statements to catch exceptions that are thrown while trying to find some environment data.
try:
path_list = env.get('PATH')
except TypeError:
path_list = None
if supports_bytes_environ:
try:
path_listb = env[b'PATH']
except (KeyError, TypeError):
pass
else:
if path_list is not None:
raise ValueError(
"env cannot contain 'PATH' and b'PATH' keys")
path_list = path_listb
if path_list is not None and isinstance(path_list, bytes):
path_list = fsdecode(path_list)
These exceptions do not signify an error and are thrown under normal conditions. When using exception breakpoints for one of these exceptions, the debugger will also break in these library functions.
Is there a way in PyCharm or in Python in general to have the debugger not break on exceptions that are thrown and caught inside a library without any involvement of my code?
in PyCharm, go to Run-->View Breakpoints, and check "On raise" and "Ignore library files".
The first option makes the debugger stop whenever an exception is raised, instead of just when the program terminates, and the second option gives PyCharm the policy to ignore library files, thus searching mainly in your code.
The solution was found thanks to CrazyCoder's link to the feature request, which has since been added.
For a while I had a complicated scheme which involved something like the following:
try( Closeable ignore = Debugger.newBreakSuppression() )
{
... library call which may throw ...
} <-- exception looks like it is thrown here
This allowed me to never be bothered by exceptions that were thrown and swallowed within library calls. If an exception was thrown by a library call and was not caught, then it would appear as if it occurred at the closing curly bracket.
The way it worked was as follows:
Closeable is an interface which extends AutoCloseable without declaring any checked exceptions.
ignore is just a name that tells IntelliJ IDEA to not complain about the unused variable, and it is necessary because silly java does not support try( Debugger.newBreakSuppression() ).
Debugger is my own class with debugging-related helper methods.
newBreakSuppression() was a method which would create a thread-local instance of some BreakSuppression class which would take note of the fact that we want break-on-exception to be temporarily suspended.
Then I had an exception breakpoint with a break condition that would invoke my Debugger class to ask whether it is okay to break, and the Debugger class would respond with a "no" if any BreakSuppression objects were instantiated.
That was extremely complicated, because the VM throws exceptions before my code has loaded, so the filter could not be evaluated during program startup, and the debugger would pop up a dialog complaining about that instead of ignoring it. (I am not complaining about that, I hate silent errors.) So, I had to have a terrible, horrible, do-not-try-this-at-home hack where the break condition would look like this: java.lang.System.err.equals( this ) Normally, this would never return
true, because System.err is not equal to a thrown exception, therefore the debugger would never break. However, when my Debugger class would get initialized, it would replace System.err with a class of its own,
which provided an implementation for equals(Object) and returned true if the debugger should break. So, essentially, I was using System.err as an eternal global variable.
Eventually I ditched this whole scheme because it is overly complicated and it performs very bad, because exceptions apparently get thrown very often in the java software ecosystem, so evaluating an expression every time an exception is thrown tremendously slows down everything.
This feature is not implemented yet, you can vote for it:
add ability to break (add breakpoint) on exceptions only for my files
There is another SO answer with a solution:
Debugging with pycharm, how to step into project, without entering django libraries
It is working for me, except I still go into the "_pydev_execfile.py" file, but I haven't stepped into other files after adding them to the exclusion in the linked answer.

How to catch IndentationError [duplicate]

This question already has answers here:
SyntaxError inconsistency in Python?
(2 answers)
Closed 5 years ago.
First of all - I don't have a problem with bad-indentated code and I have an idea of how does this exception works like.
I ask, if there is any way to catch IndentationError in code with a try/except block? For example, let's say I'm writing a test for a function written by someone else. I want to run it in try/except block and handle all warning he/she could make. I know, that it's not a best example, but the first one coming to my mind. Please, don't focus on an example, but rather on problem.
Let's look at the code:
try:
f()
except IndentationError:
print "Error"
print "Finished"
The function:
def f():
print "External function"
And the result is:
External function
Finished
And that's something, I'm ready to understand, becouse indentation in external function was consistant.
But when the function look like that:
def f():
print "External function"
print "with bad indentation"
The exception is unhandled:
print "with bad indentation"
^
IndentationError: unexpected indent
Is there any way to achieve it? I guess that's the matter of compiling, and as far I don't see any possibility to catch. Does the except IndentationError make any sense?
Yes, this can be done. However, the function under test would have to live in a different module:
# test1.py
try:
import test2
except IndentationError as ex:
print ex
# test2.py
def f():
pass
pass # error
When run, this correctly catches the exception. It is worth nothing that the checking is done on the entire module at once; I am not sure if there's a way to make it more fine-grained.
IndentationError is raised when the module is compiled. You can catch it when importing a module, since the module will be compiled on first import. You can't catch it in the same module that contains the try/except, because with the IndentationError, Python won't be able to finish compiling the module, and no code in the module will be run.
You could use a tool such as pylint, which will analyse your module and report bad indentation, as well as many other errors.

"or die()" in Python

Is anyone using anything like this in Python:
def die(error_message):
raise Exception(error_message)
...
check_something() or die('Incorrect data')
I think this kind of style is used in PHP and Perl.
Do you find any (dis)advantages in this [style]?
Well, first, sys.exit([arg]) is more common, and if you really wanted something equivalent to die in PHP, you should use that, raise a SystemExit error, or call os._exit.
The major use of the die method in PHP is, "The script has reached some impasse cannot recover from it". It is rarely, if ever, used on production code. You are better off raising an exception in a called function, catching it in the parent, and finding a graceful exit point -- that is the best way in both languages.
Lot's of good answers, but no-one has yet suggested the obvious way to write this in Python:
assert check_something(), "Incorrect data"
Just be aware that it won't do the check if you turn on optimisation, not that anyone ever does.
While that style is common in PHP and Perl, it's very un-Pythonic and I'd encourage you not to write Python that way. You should follow the conventions in the language you're using, and write something like this:
if not check_something():
raise Exception('Incorrect data')
FWIW, doing the "or die(...)" way adds another level to your stack trace, which is another minor disadvantage.
The biggest disadvantage is that all dying is now the same. Better to have check_something() raise a more accurate exception and then catch that up above if appropriate.
If you are dealing with an API that you didn't write that returns truthy values on success and falsy values on failure, that seems like a reasonably readable and compact way to do it. If you have control over the API, I'd encourage you to use exceptions instead of return values to indicate errors.
If you use the function, it probably should not be called die() unless it actually exits the program, however. If it merely raises an exception, there's no guarantee that the program will actually die. Ideally you could name it raise() as a functional version of the raise statement, but of course you can't because raise is a reserved word. Perhaps throw().
It would also be a good idea to require the caller to pass in an exception type, since Exception is rather generic and vague.
It occurs to me that this function would be unnecessary if only Python exceptions were capable of raising themselves, i.e., they had a method for it, like so:
class BaseException(object):
def throw(self):
raise self
Then you could just do:
check_something() or Exception("check failed").throw()
Sadly, Python exceptions can't raise themselves. :-)
It seems like you are just wrapping php lingo in python with a one line function. I would advise against it as you might confuse your audience. Exceptions are also a completely different beast than die in PHP.
Ideally, you would want to die/panic with a helpful stack-trace so that you can easily locate the issue.
Hence, unlike the most popular answer, you should AVOID sys.exit() or raise a SystemExit because they will cause your program to die silently(without a helpful trace).
You should use a general exception like RuntimeError that is most likely not going to be handled/caught later, and it will create a beautiful stack-trace:
def die(message):
raise RuntimeError(message)
print("hello world")
die('A helpful message')
print("hello world again")
We get the following helpful stack trace:
hello world
Traceback (most recent call last):
File "/test.py", line 9, in <module>
die("A helpful message")
File "/test.py", line 5, in die
raise RuntimeError(message)
RuntimeError: A helpful message
If I had used sys.exit instead, I would have gotten the following poor output:
import sys
def die(message):
sys.exit(message) # internally raises SystemExit
print("hello world")
die("A helpful message")
print("hello world again")
hello world
A helpful message

Categories

Resources