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

PythonCompilationSyntax Checking

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

You can check the syntax by compiling it:

python -m py_compile script.py

Solution 2 - Python

You can use these tools:

Solution 3 - Python

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.

Solution 4 - Python

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)
    

Solution 5 - Python

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

Solution 6 - Python

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.

Solution 7 - Python

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

Solution 8 - Python

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

Solution 9 - Python

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEugene YarmashView Question on Stackoverflow
Solution 1 - PythonMark JohnsonView Answer on Stackoverflow
Solution 2 - Pythonuser225312View Answer on Stackoverflow
Solution 3 - PythonRosh OxymoronView Answer on Stackoverflow
Solution 4 - Pythonjmd_dkView Answer on Stackoverflow
Solution 5 - PythonBrian C.View Answer on Stackoverflow
Solution 6 - Pythonuser1338062View Answer on Stackoverflow
Solution 7 - PythonshakhmatovView Answer on Stackoverflow
Solution 8 - PythonYordan GeorgievView Answer on Stackoverflow
Solution 9 - PythonJoshView Answer on Stackoverflow