4

I am implementing a parser for a domain specific language, and want to be able to raise a SyntaxError. How do I set the filename, lineno and offset when raising this exception?

exception SyntaxError

Raised when the parser encounters a syntax error. This may occur in an import statement, in an exec statement, in a call to the built-in function eval() or input(), or when reading the initial script or standard input (also interactively).

Instances of this class have attributes filename, lineno, offset and text for easier access to the details. str() of the exception instance returns only the message.

Source: https://docs.python.org/3.2/library/exceptions.html#SyntaxError

golightlyb
  • 49
  • 1
  • 3
  • 1
    If this isn't actually a *Python* syntax error, you might be better creating your own exception. – jonrsharpe Nov 15 '15 at 08:47
  • 2
    I would have the same problem subclassing it. As it stands, I *do* believe SyntaxError is the most appropriate type for a syntax error with filename and lineno - I'd just be reinventing it otherwise. – golightlyb Nov 15 '15 at 09:06
  • I don't mean subclassing `SyntaxError`, just your own `Exception` subclass (e.g. `class MySyntaxError(Exception):`) that you can add whatever attributes you like to. – jonrsharpe Nov 15 '15 at 09:39
  • 1
    Agree with golightly, and yet this doesn't seem settled by the wisdom of the stackoverflow crowd. https://stackoverflow.com/questions/24037690/raising-syntaxerror-inside-a-python-based-parser suggests that a SyntaxError 'might be confusing', but gives no further arguments as to what might confuse, so I remain unconvinced. SyntaxError seems like the best semantic fit, plus you get the 'sugar' of lineno, filename etc. 'for free'. – brennanyoung Nov 09 '17 at 13:00

3 Answers3

14

The answer is:

>>> raise SyntaxError('End quote missing', ("test.py", 1000, 11, "print 'bar"))                                                                             
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 1000
    print 'bar
              ^
SyntaxError: End quote missing

The second argument needs to be a 4-tuple.

dlorch
  • 211
  • 2
  • 6
1

You can have a look here: https://github.com/python/cpython/blob/master/Objects/exceptions.c#L1273

I could come up only with this:

import traceback

print("Our exception")

try:
    print("(1)")
    raise SyntaxError('Test2', {'filename': "test.py", 'lineno': 1000, 'offset': 1, 'text': "My text ..."})
except SyntaxError as inst:
    print("(2)")
    print(inst.args)
    print("(3) Get filename %s" % inst.args[1]['filename'])
    print("(4) Traceback")
    traceback.print_tb(inst.__traceback__) 

The output is then:

Our exception
(1)
(2)
('Test2', {'offset': 1, 'filename': 'test.py', 'text': 'My text ...', 'lineno': 1000})
(3) Get filename test.py
(4) Traceback
  File "test.py", line 7, in <module>
    raise SyntaxError('Test2', {'filename': "test.py", 'lineno': 1000, 'offset': 1, 'text': "My text ..."})
MartyIX
  • 27,828
  • 29
  • 136
  • 207
0

How about:

raise SyntaxError('filename: {}, lineno: {}, offset: {}'.format(
    filename, lineno, offset))
Mike Müller
  • 82,630
  • 20
  • 166
  • 161