If I have a string of Python code, how do I tell if it is valid, i.e., if entered at the Python prompt, it would raise a SyntaxError or not? I thought that using compiler.parse would work, but apparently that module has been removed in Python 3. Is there a way to do it that also works in Python 3. Obviously, I don't want to execute the code, just check its syntax.
Asked
Active
Viewed 3,934 times
19
Stefano Borini
- 132,232
- 95
- 283
- 413
asmeurer
- 80,291
- 25
- 162
- 229
-
5@goldenparrot Last time I checked, `gcc` did not have a Python frontend and static compilers in general sucked at doing dynamic languages, if they even tried. – Aug 07 '12 at 22:07
-
1@delnan waiting for gcc-python now – Stefano Borini Aug 07 '12 at 22:08
-
are you really only looking for syntax errors? or also logical errors( ie `g==5` without setting a value for g) as `g==5` will ast.parse even with no g anywhere – Joran Beasley Aug 07 '12 at 22:09
-
1@JoranBeasley Given that such errors are impossible to detect in the general case, research-level hard in many other cases, and still pretty darn expensive to find in all but the most trivial cases, I hope not for his sake. – Aug 07 '12 at 22:10
-
i think pylint would catch it (in most cases) ... – Joran Beasley Aug 07 '12 at 22:11
-
@JoranBeasley Yeah, because the example error you gave is trivial. PyLint and co. are okay, but won't catch much a quick glance won't see either. I'm not aware of any tool complaining about calls like `f(MyClass())` where `def f(x): return 1 + x` in another module, but not about `f(MyClassWith__radd__())`. – Aug 07 '12 at 22:11
-
Only syntax errors. And it needs to be part of the standard library. – asmeurer Aug 07 '12 at 22:12
2 Answers
25
Use ast.parse:
import ast
def is_valid_python(code):
try:
ast.parse(code)
except SyntaxError:
return False
return True
>>> is_valid_python('1 // 2')
True
>>> is_valid_python('1 /// 2')
False
-
I edited out the bare except. I will accept (no pun intended) this answer as soon as the site lets me. – asmeurer Aug 07 '12 at 22:15
-
4
The compiler module is now a built-in.
compile(source, filename, mode[, flags[, dont_inherit]])Compile the source into a code or AST object. Code objects can be executed by an exec statement or evaluated by a call to eval(). source can either be a string or an AST object. Refer to the ast module documentation for information on how to work with AST objects.
The AST parser is now a seperate module.
ast.parse(expr, filename='<unknown>', mode='exec')Parse an expression into an AST node. Equivalent to
compile(expr, filename, mode, ast.PyCF_ONLY_AST).
leoluk
- 11,759
- 6
- 41
- 49
-
1`compile` existed before and is nowhere the full `compiler` module. `ast` is closer. – Aug 07 '12 at 22:08
-
But `compile` wants filenames and such. I just want to check a string, not read or write to any files. – asmeurer Aug 07 '12 at 22:13
-
Just pass something like `
` as filename. Full details in the linked docs. – leoluk Aug 07 '12 at 22:15 -
Aside from that, the `compile` function has a few quirks (requires specific newline characters, and raises a TypeError out of friggin' nowhere when there are NUL bytes in the input) other options don't have. – Aug 07 '12 at 22:19