IntroductionWhat is pylint?Pylint is a tool that checks for errors in python code, tries to enforce a coding standard and looks for smelling code. This is similar but nevertheless different from what pychecker provides, especially since pychecker explicitely does not bother with coding style. The default coding style used by pylint is close to PEP 008 (aka Guido's style guide). For more information about code smells, refer to Martin Fowler's refactoring book One important thing to note is that Pylint isn't smarter than you are: it may warn you about things that you have conscientiously done. That's for example because it tries to detect things that may be dangerous in a context, but maybe not in others, or because it checks for some things that you don't care about. Generally, you shouldn't expect pylint to be totally quiet about your code, so don't necessarily be alarmed if it gives you a hell lot of messages for your proudly(XXX) project ;) Pylint will display a number of messages as it analyzes the code, as well as some statistics about the number of warnings and errors found in different files. The messages are classified under various categories such as errors and warnings (more below). If you run pylint twice, it will display the statistics from the previous run together with the ones from the current run, so that you can see if the code has improved or not. Last but not least, the code is given an overall mark, based on the number an severity of the warnings and errors. This has proven to be very motivating for programmers. InstallationDependanciesPylint requires the latest logilab-astng and logilab-common packages. It should be compatible with any python version greater than 2.2.0 (python 2.2 users will have to install the optik package). DistributionsThe source tarball is available at ftp://ftp.logilab.org/pub/pylint. You may apt-get a debian package by adding deb ftp://ftp.logilab.org/pub/debian unstable/ to your /etc/apt/sources.list file. Pylint is also available in the standard Debian distribution (but add our public debian repository anyway if you want to get the latest releases and upgrades earlier) Contributed RPM packages for pylint and logilab-common are available at ftp://ftp.nest.pld-linux.org/test. Pylint is also available in Gentoo, Fedora 4, Ubuntu, FreeBSD, Darwin (and maybe other, if si drop us a note please!). Source distribution installationFrom the source distribution, extract the tarball, go to the extracted directory and simply run python setup.py install You'll have to install dependancies in a similar way. Windows users may get valuable information about pylint installation on this page. Note for Windows usersOn Windows, once you have installed pylint, the command line usage is pylint.bat [options] module_or_package But this will only work if pylint.bat is either in the current directory, or on your system path. (setup.py install install python.bat to the Scripts subdirectory of your Python installation -- e.g. C:Python24Scripts.) You can do any of the following to solve this:
To effect (2), simply append the appropriate directory name to the PATH= statement in autoexec.bat. Be sure to use the Windows directory separator of ';' between entries. Then, once you have rebooted (this is necessary so that the new path statement will take effect when autoexec.bat is run), you will be able to invoke PyLint with pylint.bat on the command line. (3) is the best solution. Once done, you can call pylint at the command line without the .bat, just as do non-Windows users by typing: pylint [options] module_or_package To effect option (3), simply create a plain text file pylint.bat with the single line: C:\PythonDirectory\Scripts\pylint.bat (where PythonDirectory is replaced by the actual Python installation directory on your system -- e.g. C:Python24Scriptspylint.bat). Invoking pylintPylint is meant to be called from the command line. The usage is pylint [options] module_or_package You should give pylint the name of a Python package or module. Pylint will import this package or module, so you should pay attention to your PYTHONPATH, since it is a common error to analyze an installed version of a module instead of the development version. It is also possible to analyze python files, with a few restriction. The thing to keep in mind is that pylint will try to convert the file name to a module name, and only be able to process the file if it succeeds. pylint mymodule.py should always work since the current working directory is automatically added on top of the python path pylint directory/mymodule.py will work if "directory" is a python package (i.e. has an __init__.py file) or if "directory" is in the python path. For more details on this see the Frequently Asked Questions. You can also start a thin gui around pylint (require TkInter) by typing pylint-gui This should open a window where you can enter the name of the package or module to check, at pylint messages will be displayed in the user interface. Pylint outputThe default format for the output is raw text. But passing pylint the --html option will produce an HTML document. There are several sections in pylint's output. Source code analysis sectionFor each python module, pylint will first display a few '*' characters followed by the name of the module. Then, a number of messages with the following format: MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE You can get another output format, useful since it's recognized by most editors or other development tools using the --parseable=y option. The message type can be:
Sometimes the line of code which caused the error is displayed with a caret pointing to the error. This may be generalized in future versions of pylint. Example (extracted from a run of pylint on itself...):
************* Module pylint.checkers.format
W: 50: Too long line (86/80)
W:108: Operator not followed by a space
print >>sys.stderr, 'Unable to match %r', line
^
W:141: Too long line (81/80)
W: 74:searchall: Unreachable code
W:171:FormatChecker.process_tokens: Redefining built-in (type)
W:150:FormatChecker.process_tokens: Too many local variables (20/15)
W:150:FormatChecker.process_tokens: Too many branchs (13/12)
Reports sectionFollowing the analysis message, pylint will display a set of reports, each one focusing on a particular aspect of the project, such as number of messages by categories, modules dependancies... For instance, the metrics report displays summaries gathered from the current run.
Also, a global evaluation for the code is computed, and an optional witty comment is displayed (if --comment=y was specified on the command line). Command line optionsFirst of all, we have two basic (but useful) options.
Pylint is architectured around several checkers. By default all checkers are enabled. You can disable a specific checker by specifying --enable-<checker>=n, or disable all checkers using --disable-all and afterwards enable specific checkers with --enable-<checker>=y. See the list of available features for a description of provided checkers with their functionalities. Each checker has some specific options, which can take either a yes/no value, an integer, a python regular expression, or a comma separated list of values (which are generally used to override a regular expression in special cases). For a full list of options, use --help Specifying all the options suitable for your setup and coding standards can be tedious, so it is possible to use a rc file to specify the default values. Pylint looks for /etc/pylintrc and ~/.pylintrc. The --generate-rcfile option will generate a commented configuration file according to the current configuration on standard output and exit. You can put other options before this one to use them in the configuration, or start with the default values and hand tune the configuration. Other useful global options include:
Daily pylint usageWhat pylint says is not to be taken as gospel. While getting as few false positives for errors as possible is a goal for us -- and python makes it hard enough, it is not the case for warnings.
Bug reports, feedbackYou think you have found a bug in Pylint? Well, this may be the case since Pylint is under development. Please take the time to send a bug report to python-projects@logilab.org if you've not found it already reported on the tracker page. This mailing list is also a nice place to discuss Pylint issues, see below for more information about pylint's related lists. You can check for already reported bugs, planned features on pylint's tracker web page: http://www.logilab.org/project/name/pylint Notice that if you don't find something you have expected in pylint's tracker page, it may be on the tracker page of one of its dependancies, namely astng and common: Mailing listsUse the python-projects@logilab.org mailing list for anything related to Pylint. This is in most cases better than sending an email directly to the author, since others will benefit from the exchange, and you'll be more likely answered by someone subscribed to the list. This is a moderated mailing list, so if you're not subscribed email you send will have to be validated first before actually being sent on the list. You can subscribe to this mailing list at http://lists.logilab.org/mailman/listinfo/python-projects Archives are available at http://lists.logilab.org/pipermail/python-projects/ If you prefer speaking french instead of english, you can use the generic forum-fr@logilab.org mailing list:
Notice though that this list has a very low traffic since most pylint related discussions are done on the python-projects mailing list. Advanced usageBase configurationTo be written... EnvironmentTo be written... Messages controlAn example available from the examples directory:
"""pylint option block-disable-msg"""
__revision__ = None
class Foo(object):
"""block-disable-msg test"""
def __init__(self):
pass
def meth1(self, arg):
"""this issues a message"""
print self
def meth2(self, arg):
"""and this one not"""
# pylint: disable-msg=W0613
print self\
+ "foo"
def meth3(self):
"""test one line disabling"""
# no error
print self.bla # pylint: disable-msg=E1101
# error
print self.blop
def meth4(self):
"""test re-enabling"""
# pylint: disable-msg=E1101
# no error
print self.bla
print self.blop
# pylint: enable-msg=E1101
# error
print self.blip
def meth5(self):
"""test IF sub-block re-enabling"""
# pylint: disable-msg=E1101
# no error
print self.bla
if self.blop:
# pylint: enable-msg=E1101
# error
print self.blip
else:
# no error
print self.blip
# no error
print self.blip
def meth6(self):
"""test TRY/EXCEPT sub-block re-enabling"""
# pylint: disable-msg=E1101
# no error
print self.bla
try:
# pylint: enable-msg=E1101
# error
print self.blip
except UndefinedName: # pylint: disable-msg=E0602
# no error
print self.blip
# no error
print self.blip
def meth7(self):
"""test one line block opening disabling"""
if self.blop: # pylint: disable-msg=E1101
# error
print self.blip
else:
# error
print self.blip
# error
print self.blip
def meth8(self):
"""test late disabling"""
# error
print self.blip
# pylint: disable-msg=E1101
# no error
print self.bla
print self.blop
Enhancing PylintWriting your own checkerYou can find some simple examples in the examples directory of the distribution (custom.py and custom_raw.py). I'll try to quickly explain the essentials here. First, there are two kinds of checkers : * raw checkers, which are analysing each module as a raw file stream * ast checkers, which are working on an ast representation of the module The ast representation used is an extension of the one provided with the standard python distribution in the compiler package. The extension adds additional information and methods on the tree nodes to ease navigation and code introspection. An AST checker is a visitor, and should implement visit_<lowered class name> leave_<lowered class name> methods for the nodes it's interested in. To get description of the different classes used in an ast tree, look at the compiler.ast documentation. Checkers are ordered by priority. For each module, pylint's engine:
Notice that the source code is probably the best source of documentation, it should be clear and well documented. Don't hesitate to ask for any information on the python-projects mailing list. Contribute !All our software is developped using the mercurial version control system. This is a very cool distributed vcs and its usage is very similar to other ones such as cvs or subversion (though the distributed feature introduced some different usage patterns). See mercurial home page for installation on your computer and basic usage. Note that it's very easy to send us patches using hg email command ;). You can get the in-development pylint source code from our public mercurial repository: http://www.logilab.org/src/pylint The same is true for pylint dependancies (if you use pylint code from the repository, you should usually use code from the repository as well for astng and common): http://www.logilab.org/src/logilab/astng http://www.logilab.org/src/logilab/common Other informationIDE integrationPylint is integrated in the following editors/IDEs:
To use pylint from within vim, see http://www.gonzo.kiev.ua/projects/pylint.vim To use pylint from within komodo, see http://mateusz.loskot.net/2006/01/15/running-pylint-from-komodo/ To use pylint from within gedit, see http://live.gnome.org/Gedit/PylintPlugin Some projects using PylintThe following projects are known to use pylint to help develop better code:
Also notice that the CheeseCake kwalitee reporting tool uses pylint to analyze the source code. | |||||||||||||||||||||||||||||||||||||||||||||||||||||


Comments
(add comment)PyLint is integrated in WingIDE as well.
Hi,
Here you mentioned Pylint requires the latest logilab-astng and logilab-common packages. But nothing is there in those links. Could you please help me to download the same.
Thank you.
Sivaraman
I fixed the links.
Thank you.
Hi,
Here you mentioned in the user manual "Pylint requires the latest logilab-astng and logilab-common packages". But it has many thing to download as a dependancy. Kindly tell me that what are the things i have to download from those dependancy folder.
Thank you.
Sivaraman.
Pylint's documentation is not the best place to document the dependencies of logilab-astng and logilab-common... but since they depend only on the standard library and egenix's mx.datetime, it should be easy to get them installed on your system.
PyLint is also supported by the Wings IDE
PyLint is integrated with PyScripter too.
Is there any suggestions how to tune up and drive pylint right?
Thank you.
Traceback below:
Traceback (most recent call last): File "C:\Python24\Scripts\pylint.bat", line 12, in ? lint.Run(sys.argv[1:]) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 891, in __init__ linter.check(args) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 502, in check self.check_astng_module(astng, checkers) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 578, in check_astng_module self.astng_events(astng, [checker for checker in checkers File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 596, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 596, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 596, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 596, in astng_events self.astng_events(child, checkers, _reversed_checkers) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\lint.py", line 593, in astng_events checker.visit(astng) File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\utils.py", line 323, in visit method(node) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\checkers\typecheck.py", line 200, in visit_assign function_node = safe_infer(node.value.func) File "c:\python24\lib\site-packages\pylint-0.19.0-py2.4.egg\pylint\checkers\utils.py", line 38, in safe_infer value = inferit.next() File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 253, in infer_getattr for owner in self.expr.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 168, in _infer_stmts for infered in stmt.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 391, in infer_ass stmts = list(self.assigned_stmts(context=context)) File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\protocols.py", line 180, in for_assigned_stmts for infered in _resolve_looppart(self.iter.infer(context), asspath, context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\protocols.py", line 142, in _resolve_looppart for part in parts: File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 207, in infer_callfunc for infered in callee.infer_call_result(self, callcontext): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\scoped_nodes.py", line 426, in infer_call_result for infered in returnnode.value.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 201, in infer_callfunc for callee in self.func.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 253, in infer_getattr for owner in self.expr.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 259, in infer_getattr for obj in owner.igetattr(self.attrname, context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 168, in _infer_stmts for infered in stmt.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 168, in _infer_stmts for infered in stmt.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 168, in _infer_stmts for infered in stmt.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 168, in _infer_stmts for infered in stmt.infer(context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 203, in wrapped for res in _func(node, context, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 231, in wrapper for node in func(*args, **kwargs): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\inference.py", line 259, in infer_getattr for obj in owner.igetattr(self.attrname, context): File "c:\python24\lib\site-packages\logilab_astng-0.19.3-py2.4.egg\logilab\astng\infutils.py", line 168, in _infer_stmts for infered in stmt.infer(context): KeyboardInterruptIf you want to ask questions about pylint, please use the mailing list at http://lists.logilab.org/mailman/listinfo/python-projects
Comments attached to the manual must be about the manual, not troubleshooting your personnal setup.
I will remove your comment and my answer within seven days or once you read it and contact the mailing list.
If you want to add Wing IDE to the IDE support section, the link would be http://www.wingware.com/doc/edit/pylint
added, thanks