1

I just want the simplest possible way for my Python script to ask "is the Python code which I just generated syntactically valid Python?"

I tried:

try:  
    import py_compile  
    x = py_compile.compile(generatedScriptPath, doraise=True)  
    pass  

except py_compile.PyCompileError, e:
    print str(e)
    pass

But even with a file containing invalid Python, the exception is not thrown and afterwards x == None.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551
  • 1
    Can you simply try to import generated module and catch ImportError (if module's missing) or SyntaxError (if module is invalid)? Alternativly, `ast.parse` would raise an exception during parsing an invalid Python code. – Łukasz Rogalski Mar 04 '16 at 12:45
  • 1
    What do you mean by invalid Python? – Selcuk Mar 04 '16 at 12:45
  • If you simply want to parse the module you could use the [`ast`](https://docs.python.org/2/library/ast.html) module's [`parse`](https://docs.python.org/2/library/ast.html#ast.parse) function. In fact there is a [`compile`](https://docs.python.org/2/library/functions.html#compile) built-in function that can be used to do that. – Bakuriu Mar 04 '16 at 12:46
  • @Rogalski Yeah... and what if that file is user provided and contains malicious code? – Bakuriu Mar 04 '16 at 12:47
  • @Bakuriu "code which I just generated" suggest that code author may be trusted. – Łukasz Rogalski Mar 04 '16 at 12:47
  • Why do you need to test if the code YOU generated is valid? – Mr. E Mar 04 '16 at 12:50
  • 1
    It gives an exception for me. What did you try for 'invalid Python code'? – Selcuk Mar 04 '16 at 12:50

1 Answers1

4

There is no need to use py_compile. It's intended use is to write a bytecode file from the given source file. In fact it will fail if you don't have the permissions to write in the directory, and thus you could end up with some false negatives.

To just parse, and thus validate the syntax, you can use the ast module to parse the contents of the file, or directly call the compile built-in function.

import ast

def is_valid_python_file(fname):
    with open(fname) as f:
        contents = f.read()
    try:
        ast.parse(contents)
        #or compile(contents, fname, 'exec', ast.PyCF_ONLY_AST)
        return True
    except SyntaxError:
        return False

Be sure to not execute the file, since if you cannot trust its contents (and if you don't even know whether the file contains valid syntax I doubt you can actually trust the contents even if you generated them) you could end up executing malicious code.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • 1
    FYI: `py_compile` is also a [standard library](https://docs.python.org/2/library/py_compile.html). – Selcuk Mar 04 '16 at 12:52