I would like to get some feedback on these tools on:
A simple program which checks Python source files for errors. Pyflakes analyzes programs and detects various errors. It works by parsing the source file, not importing it, so it is safe to use on modules with side effects. It's also much faster.
To use PyChecker, pass options and the python source files (or packages) you want to check on the command line: pychecker [options] file1.py file2.py ... Note: On Windows, use pychecker.
Pylint analyses your code without actually running it. It checks for errors, enforces a coding standard, looks for code smells, and can make suggestions about how the code could be refactored. Pylint can infer actual values from your code using its internal code representation (astroid).
Well, I am a bit curious, so I just tested the three myself right after asking the question ;-)
Ok, this is not a very serious review, but here is what I can say:
I tried the tools with the default settings (it's important because you can pretty much choose your check rules) on the following script:
#!/usr/local/bin/python # by Daniel Rosengren modified by e-satis import sys, time stdout = sys.stdout BAILOUT = 16 MAX_ITERATIONS = 1000 class Iterator(object) : def __init__(self): print 'Rendering...' for y in xrange(-39, 39): stdout.write('\n') for x in xrange(-39, 39): if self.mandelbrot(x/40.0, y/40.0) : stdout.write(' ') else: stdout.write('*') def mandelbrot(self, x, y): cr = y - 0.5 ci = x zi = 0.0 zr = 0.0 for i in xrange(MAX_ITERATIONS) : temp = zr * zi zr2 = zr * zr zi2 = zi * zi zr = zr2 - zi2 + cr zi = temp + temp + ci if zi2 + zr2 > BAILOUT: return i return 0 t = time.time() Iterator() print '\nPython Elapsed %.02f' % (time.time() - t)
As a result:
PyChecker
is troublesome because it compiles the module to analyze it. If you don't want your code to run (e.g, it performs a SQL query), that's bad.PyFlakes
is supposed to be light. Indeed, it decided that the code was perfect. I am looking for something quite severe so I don't think I'll go for it.PyLint
has been very talkative and rated the code 3/10 (OMG, I'm a dirty coder !).Strong points of PyLint
:
Cons of Pylint:
Corrected script (with lazy doc strings and variable names):
#!/usr/local/bin/python # by Daniel Rosengren, modified by e-satis """ Module doctring """ import time from sys import stdout BAILOUT = 16 MAX_ITERATIONS = 1000 def mandelbrot(dim_1, dim_2): """ function doc string """ cr1 = dim_1 - 0.5 ci1 = dim_2 zi1 = 0.0 zr1 = 0.0 for i in xrange(MAX_ITERATIONS) : temp = zr1 * zi1 zr2 = zr1 * zr1 zi2 = zi1 * zi1 zr1 = zr2 - zi2 + cr1 zi1 = temp + temp + ci1 if zi2 + zr2 > BAILOUT: return i return 0 def execute() : """ func doc string """ print 'Rendering...' for dim_1 in xrange(-39, 39): stdout.write('\n') for dim_2 in xrange(-39, 39): if mandelbrot(dim_1/40.0, dim_2/40.0) : stdout.write(' ') else: stdout.write('*') START_TIME = time.time() execute() print '\nPython Elapsed %.02f' % (time.time() - START_TIME)
Thanks to Rudiger Wolf, I discovered pep8
that does exactly what its name suggests: matching PEP8. It has found several syntax no-nos that Pylint did not. But Pylint found stuff that was not specifically linked to PEP8 but interesting. Both tools are interesting and complementary.
Eventually I will use both since there are really easy to install (via packages or setuptools) and the output text is so easy to chain.
To give you a little idea of their output:
pep8:
./python_mandelbrot.py:4:11: E401 multiple imports on one line ./python_mandelbrot.py:10:1: E302 expected 2 blank lines, found 1 ./python_mandelbrot.py:10:23: E203 whitespace before ':' ./python_mandelbrot.py:15:80: E501 line too long (108 characters) ./python_mandelbrot.py:23:1: W291 trailing whitespace ./python_mandelbrot.py:41:5: E301 expected 1 blank line, found 3
Pylint:
************* Module python_mandelbrot C: 15: Line too long (108/80) C: 61: Line too long (85/80) C: 1: Missing docstring C: 5: Invalid name "stdout" (should match (([A-Z_][A-Z0-9_]*)|(__.*__))$) C: 10:Iterator: Missing docstring C: 15:Iterator.__init__: Invalid name "y" (should match [a-z_][a-z0-9_]{2,30}$) C: 17:Iterator.__init__: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) [...] and a very long report with useful stats like : Duplication ----------- +-------------------------+------+---------+-----------+ | |now |previous |difference | +=========================+======+=========+===========+ |nb duplicated lines |0 |0 |= | +-------------------------+------+---------+-----------+ |percent duplicated lines |0.000 |0.000 |= | +-------------------------+------+---------+-----------+
pep8 was recently added to PyPi.
It is now super easy to check your code against pep8.
See http://pypi.python.org/pypi/pep8
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With