Checking python syntax of a string in Python? - python

Lets say I have a string
s="""
print 'hi'
print 'hi'
print 3333/0
"""
Is there a module or way that can help me check the syntax of this string?
I would like the output to be like:
Line 2, indentation
Line 3, Division by Zero
I have heard of pyFlakes, pyChecker and pyLint but those check a file, not a string.

The compile() function will tell you about compile-time errors:
try:
compile(s, "bogusfile.py", "exec")
except Exception as e:
print "Problem: %s" % e
Keep in mind though: one error will prevent the others from being reported, and some of your errors (ZeroDivision) are a run-time error, not something the compiler detects.

s="""
print 'hi'
print 'hi'
print 3333/0
"""
eval(s)
output:
Traceback (most recent call last):
File "prog.py", line 7, in <module>
eval(s)
File "<string>", line 3
print 'hi'
^
SyntaxError: invalid syntax

Related

Python3: Is it possible to make a error not show the line of code that caused the error?

I want to know if it's possible to make a traceback not show the line of code that caused the error.
I don't want:
>>> print("hi"f)
File "<stdin>", line 1
print("hi"f)
^
SyntaxError: invalid syntax
I do want:
>>> print("hi"f)
File "<stdin>", line 1
SyntaxError: invalid syntax
You can just prevent the error altogether by using try and except
try:
print("hello"f)
except:
print("found error");
Now, as you can see, there is an error on the first line, and when ever python interpreter finds that error, instead of calling a traceback, it just runs the code in the except block...
I just wrote helper function ExcText(), you can see how I used it inside test() function. If you call it as ExcText(False) then lines of code are not printed, if ExcText(True) then they are printed.
Try it online!
def ExcText(show_lines):
import sys, traceback
r = traceback.StackSummary.extract(traceback.walk_tb(sys.exc_info()[2]))
if not show_lines:
for i, e in enumerate(r):
r[i]._line = ''
return ''.join(['Traceback (most recent call last):\n'] + r.format() +
traceback.format_exception_only(*sys.exc_info()[:2]))
def test():
try:
def g():
assert False, 'Hello, World!'
def f():
g()
f()
except:
print(ExcText(False))
test()
Output for ExcText(False):
Traceback (most recent call last):
File "C:\t\test.py", line 16, in test
File "C:\t\test.py", line 15, in f
File "C:\t\test.py", line 13, in g
AssertionError: Hello, World!
Output for ExcText(True):
Traceback (most recent call last):
File "C:\t\test.py", line 16, in test
f()
File "C:\t\test.py", line 15, in f
g()
File "C:\t\test.py", line 13, in g
assert False, 'Hello, World!'
AssertionError: Hello, World!
You can also use code above to catch Syntax Errors, just do compile(program_text, '<string>', 'exec'), where program text is a string containing text of script that needs to be checked, example of code is here. You may also read program text from file through:
with open(filename, 'r', encoding = 'utf-8') as f:
prog = f.read()
You should use compile() instead of exec() when you only need syntax check, because script (program text) may contain some malicious code (like trojan) and exec() will execute it after checking syntax, while compile() will not execute, just checks that it is compilable and has no syntax errors.
Also non-printing of code lines can be achieved by hack with patching linecache.getline() function, like below.
But beware that this solution modifies standard module, so it is a hack that should be avoided if possible. First solution above is better.
Try it online!
def test():
import traceback
traceback.linecache.getline = lambda *pargs, **nargs: ''
try:
def g():
assert False, 'Hello, World!'
def f():
g()
f()
except:
traceback.print_exc()
test()
Output:
Traceback (most recent call last):
File "C:\t\test.py", line 10, in test
File "C:\t\test.py", line 9, in f
File "C:\t\test.py", line 7, in g
AssertionError: Hello, World!

Why doesn't an undefined name in an "except" raise a NameError?

I was surprised today to see that the following works with no exceptions (in Python 2.7.3 at least):
>>> try:
... pass
... except ThingThatDoesNotExist:
... print "bad"
...
>>>
I would have thought that this should raise a NameError in the REPL, similar to how the following would:
>>> x = ThingThatDoesNotExist
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'ThingThatDoesNotExist' is not defined
Anyone have any idea what's going on here?
The same reason this does not raise a exception:
>>> True or ThingThatDoesNotExist
Python looks up names exactly the moment they need to be evaluated. Names that don't need to be evaluated are not looked up and it's the failed lookup that raises the exception.

While function python

Hello is use eclipse and pydev, I was wondering why my sample code won't work trying to use the while function.
print("Welcome to the annoying program")
response = ""
while response != "Because.":
response = input("why\n")
print("Oh,ok")
the output is the following:
Welcome to the annoying program
why
Because.
Traceback (most recent call last):
File "/Users/calebmatthias/Document/workspace/de.vogella.python.first/simpprogram.py", l ine 9, in <module>
response = input("why\n")
File "/Users/calebmatthias/Desktop/eclipse 2/plugins/org.python.pydev_2.2.3.2011100616/PySrc/pydev_sitecustomize/sitecustomize.py", line 210, in input
return eval(raw_input(prompt))
File "<string>", line 1
Because.
^
SyntaxError: unexpected EOF while parsing
The input function in 2.x evaluates the input as Python code! Use the raw_input function instead.
With input, your text "Because." is being evaluated, and it's a syntax error because the dot isn't followed by anything.

How can I get better error information with try/except in Python

Consider this try/except block I use for checking error message stored in e.
Try/Catch to get the e
queryString = "SELECT * FROM benchmark WHERE NOC = 2"
try:
res = db.query(queryString)
except SQLiteError, e:
# `e` has the error info
print `e`
The e object here contains nothing more than the above string. When python reports an unhandled error, however, it shows a pretty detailed info as below:
Traceback (most recent call last):
File "fool.py", line 1, in
open("abc.zyz", "r")
IOError: [Errno 2] No such file or directory: 'abc.zyz'
My question is, how can I get the information such as above (the file and the line number etc.)? Or, if e contains this info, how is it stored inside it?
This will show the trace to the error.
import traceback
try:
res = db.query(queryString)
except SQLiteError, e:
# `e` has the error info
print `e`
for tb in traceback.format_tb(sys.exc_info()[2]):
print tb
Like the first 2 answers, use traceback. Here is a more complete example.
import traceback
def foo():
raise RuntimeError('we have a problem')
try:
foo()
except:
traceback.print_exc()
When you run it, you'll see
Traceback (most recent call last):
File "C:\0\tmp\x.py", line 6, in <module>
foo()
File "C:\0\tmp\x.py", line 3, in foo
raise RuntimeError('we have a problem')
RuntimeError: we have a problem
See the traceback library.
If you want to just pass errors up the chain instead of modifying them, you can just use raise within an except block, which will then act like the except block isn't there (aside from any conditional logic/side effects you may have done before the raise).

How can I convert string to "command" in Python?

How can I convert this so it could execute?
Traceback (most recent call last):
File "C:\Users\Shady\Desktop\tet.py", line 14, in <module>
exec test
File "<string>", line 1
print "hello world"
^
IndentationError: unexpected indent
source:
test = ''.join(clientIp.split("test6")[1:])
You might need to use lstrip() on the string to get rid of any leading whitespace before passing it to exec.

Categories