How can I check the syntax of Python script without executing it?

Question:

I used to use perl -c programfile to check the syntax of a Perl program and then exit without executing it. Is there an equivalent way to do this for a Python script?

Asked By: Eugene Yarmash

||

Answers:

You can use these tools:

Answered By: user225312
import sys
filename = sys.argv[1]
source = open(filename, 'r').read() + 'n'
compile(source, filename, 'exec')

Save this as checker.py and run python checker.py yourpyfile.py.

Answered By: Rosh Oxymoron

You can check the syntax by compiling it:

python -m py_compile script.py
Answered By: Mark Johnson

Perhaps useful online checker PEP8 : http://pep8online.com/

Answered By: shakhmatov

for some reason ( I am a py newbie … ) the -m call did not work …

so here is a bash wrapper func …

# ---------------------------------------------------------
# check the python synax for all the *.py files under the
# <<product_version_dir/sfw/python
# ---------------------------------------------------------
doCheckPythonSyntax(){

    doLog "DEBUG START doCheckPythonSyntax"

    test -z "$sleep_interval" || sleep "$sleep_interval"
    cd $product_version_dir/sfw/python
    # python3 -m compileall "$product_version_dir/sfw/python"

    # foreach *.py file ...
    while read -r f ; do 

        py_name_ext=$(basename $f)
        py_name=${py_name_ext%.*}

        doLog "python3 -c "import $py_name""
        # doLog "python3 -m py_compile $f"

        python3 -c "import $py_name"
        # python3 -m py_compile "$f"
        test $! -ne 0 && sleep 5

    done < <(find "$product_version_dir/sfw/python" -type f -name "*.py")

    doLog "DEBUG STOP  doCheckPythonSyntax"
}
# eof func doCheckPythonSyntax
Answered By: Yordan Georgiev

Here’s another solution, using the ast module:

python -c "import ast; ast.parse(open('programfile').read())"

To do it cleanly from within a Python script:

import ast, traceback

filename = 'programfile'
with open(filename) as f:
    source = f.read()
valid = True
try:
    ast.parse(source)
except SyntaxError:
    valid = False
    traceback.print_exc()  # Remove to silence any errros
print(valid)
Answered By: jmd_dk

Pyflakes does what you ask, it just checks the syntax. From the docs:

Pyflakes makes a simple promise: it will never complain about style, and it will try very, very hard to never emit false positives.

Pyflakes is also faster than Pylint or Pychecker. This is largely because Pyflakes only examines the syntax tree of each file individually.

To install and use:

$ pip install pyflakes
$ pyflakes yourPyFile.py
Answered By: Brian C.

Thanks to the above answers @Rosh Oxymoron. I improved the script to scan all files in a dir that are python files. So for us lazy folks just give it the directory and it will scan all the files in that directory that are python.

import sys
import glob, os

os.chdir(sys.argv[1])
for file in glob.glob("*.py"):
    source = open(file, 'r').read() + 'n'
    compile(source, file, 'exec')

Save this as checker.py and run python checker.py ~/YOURDirectoryTOCHECK

Answered By: Josh
python -m compileall -q .

Will compile everything under current directory recursively, and print only errors.

$ python -m compileall --help
usage: compileall.py [-h] [-l] [-r RECURSION] [-f] [-q] [-b] [-d DESTDIR] [-x REGEXP] [-i FILE] [-j WORKERS] [--invalidation-mode {checked-hash,timestamp,unchecked-hash}] [FILE|DIR [FILE|DIR ...]]

Utilities to support installing Python libraries.

positional arguments:
  FILE|DIR              zero or more file and directory names to compile; if no arguments given, defaults to the equivalent of -l sys.path

optional arguments:
  -h, --help            show this help message and exit
  -l                    don't recurse into subdirectories
  -r RECURSION          control the maximum recursion level. if `-l` and `-r` options are specified, then `-r` takes precedence.
  -f                    force rebuild even if timestamps are up to date
  -q                    output only error messages; -qq will suppress the error messages as well.
  -b                    use legacy (pre-PEP3147) compiled file locations
  -d DESTDIR            directory to prepend to file paths for use in compile-time tracebacks and in runtime tracebacks in cases where the source file is unavailable
  -x REGEXP             skip files matching the regular expression; the regexp is searched for in the full path of each file considered for compilation
  -i FILE               add all the files and directories listed in FILE to the list considered for compilation; if "-", names are read from stdin
  -j WORKERS, --workers WORKERS
                        Run compileall concurrently
  --invalidation-mode {checked-hash,timestamp,unchecked-hash}
                        set .pyc invalidation mode; defaults to "checked-hash" if the SOURCE_DATE_EPOCH environment variable is set, and "timestamp" otherwise.

Exit value is 1 when syntax errors have been found.

Thanks C2H5OH.

Answered By: user1338062