DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • How Agile Works at Tesla [Video]
  • Integrating AWS With Salesforce Using Terraform
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • What to Pay Attention to as Automation Upends the Developer Experience

Trending

  • How Agile Works at Tesla [Video]
  • Integrating AWS With Salesforce Using Terraform
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • What to Pay Attention to as Automation Upends the Developer Experience
  1. DZone
  2. Coding
  3. Languages
  4. PyLint: Analyzing Python Code

PyLint: Analyzing Python Code

Mike Driscoll user avatar by
Mike Driscoll
·
Jun. 14, 12 · Interview
Like (1)
Save
Tweet
Share
7.09K Views

Join the DZone community and get the full member experience.

Join For Free

Python code analysis can be a heavy subject, but it can be very helpful in making your programs better. There are several Python code analyzers that you can use to check your code and see if they conform to standards. pylint is probably the most popular. It’s very configurable, customizable and pluggable too. It also checks your code to see if it conforms to PEP8, the official style guide of Python Core and it looks for programming errors too. We’re going to spend a few minutes looking at some of the things you can do with this handy tool.

Getting Started

 

Sadly, pylint isn’t included with Python, so you’ll need to go out and download it from Logilab or PyPI. If you have SetupTools installed, then you can install it using easy_install, like this:


easy_install pylint

Now you should have pylint installed and ready to roll!

Analyzing Your Code

 

The latest version as of this writing is 0.25.1. Once pylint is installed, you can run it on the command line without any arguments to see what options it accepts. Now we need some code to test with. Since I wrote some crummy code for my PyChecker article last year, we’ll re-use that here and see if pylint picks up the same problems. There should be four issues. Here’s the code:

import sys
 
########################################################################
class CarClass:
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self, color, make, model, year):
        """Constructor"""
        self.color = color
        self.make = make
        self.model = model
        self.year = year
 
        if "Windows" in platform.platform():
            print "You're using Windows!"
 
        self.weight = self.getWeight(1, 2, 3)
 
    #----------------------------------------------------------------------
    def getWeight(this):
        """"""
        return "2000 lbs"

Now let’s run pylint against this code and see what it finds. You should get something like the following:


C:\Users\mdriscoll\Desktop>pylint crummy_code.py
No config file found, using default configuration
************* Module crummy_code
C: 1,0: Missing docstring
C: 4,0:CarClass: Empty docstring
E: 15,24:CarClass.__init__: Undefined variable 'platform'
E: 18,22:CarClass.__init__: Too many positional arguments for function call
E: 21,4:CarClass.getWeight: Method should have "self" as first argument
C: 21,4:CarClass.getWeight: Invalid name "getWeight" (should match [a-z_][a-z0-9
_]{2,30}$)
C: 21,4:CarClass.getWeight: Empty docstring
R: 21,4:CarClass.getWeight: Method could be a function
R: 4,0:CarClass: Too few public methods (1/2)
W: 1,0: Unused import sys

Report
======
13 statements analysed.

Messages by category
--------------------

+-----------+-------+---------+-----------+
|type |number |previous |difference |
+===========+=======+=========+===========+
|convention |4 |NC |NC |
+-----------+-------+---------+-----------+
|refactor |2 |NC |NC |
+-----------+-------+---------+-----------+
|warning |1 |NC |NC |
+-----------+-------+---------+-----------+
|error |3 |NC |NC |
+-----------+-------+---------+-----------+

Messages
--------

+-----------+------------+
|message id |occurrences |
+===========+============+
|C0112 |2 |
+-----------+------------+
|W0611 |1 |
+-----------+------------+
|R0903 |1 |
+-----------+------------+
|R0201 |1 |
+-----------+------------+
|E1121 |1 |
+-----------+------------+
|E0602 |1 |
+-----------+------------+
|E0213 |1 |
+-----------+------------+
|C0111 |1 |
+-----------+------------+
|C0103 |1 |
+-----------+------------+

Global evaluation
-----------------
Your code has been rated at -6.92/10

Statistics by type
------------------

+---------+-------+-----------+-----------+------------+---------+
|type |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module |1 |NC |NC |0.00 |0.00 |
+---------+-------+-----------+-----------+------------+---------+
|class |1 |NC |NC |0.00 |0.00 |
+---------+-------+-----------+-----------+------------+---------+
|method |2 |NC |NC |50.00 |50.00 |
+---------+-------+-----------+-----------+------------+---------+
|function |0 |NC |NC |0 |0 |
+---------+-------+-----------+-----------+------------+---------+

Raw metrics
-----------

+----------+-------+------+---------+-----------+
|type |number |% |previous |difference |
+==========+=======+======+=========+===========+
|code |12 |63.16 |NC |NC |
+----------+-------+------+---------+-----------+
|docstring |4 |21.05 |NC |NC |
+----------+-------+------+---------+-----------+
|comment |3 |15.79 |NC |NC |
+----------+-------+------+---------+-----------+
|empty |0 |0.00 |NC |NC |
+----------+-------+------+---------+-----------+

Duplication
-----------

+-------------------------+------+---------+-----------+
| |now |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines |0 |NC |NC |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |NC |NC |
+-------------------------+------+---------+-----------+

If you want to know what those items in the Messages section mean with their cryptic ids, you can make pylint tell you by doing this on the command line:


pylint --help-msg=C0112

However, we really only care about the first section of the report as the rest is basically just tables showing the same information in a more obscure manner. Let’s take a look at that section more closely:


C: 1,0: Missing docstring
C: 4,0:CarClass: Empty docstring
E: 15,24:CarClass.__init__: Undefined variable 'platform'
E: 18,22:CarClass.__init__: Too many positional arguments for function call
E: 21,4:CarClass.getWeight: Method should have "self" as first argument
C: 21,4:CarClass.getWeight: Invalid name "getWeight" (should match [a-z_][a-z0-9
_]{2,30}$)
C: 21,4:CarClass.getWeight: Empty docstring
R: 21,4:CarClass.getWeight: Method could be a function
R: 4,0:CarClass: Too few public methods (1/2)
W: 1,0: Unused import sys

First we need to figure out what the letters designate: C is for convention, R is refactor, W is warning and E is error. pylint found 3 errors, 4 convention issues, 2 lines that might be worth refactoring and 1 warning. The 3 errors plus the warning were what I was looking for. We should try to make this crummy code better and reduce the number of issues. We’ll fix the imports and change the getWeight function to get_weight since camelCase isn’t allowed for method names. We also need to fix the call to get_weight so it passes the right number of arguments and fix it so it has “self” as the first argument. Here’s the new code:

# crummy_code_fixed.py
import platform
 
########################################################################
class CarClass:
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self, color, make, model, year):
        """Constructor"""
        self.color = color
        self.make = make
        self.model = model
        self.year = year
 
        if "Windows" in platform.platform():
            print "You're using Windows!"
 
        self.weight = self.get_weight(3)
 
    #----------------------------------------------------------------------
    def get_weight(self, this):
        """"""
        return "2000 lbs" 

Let’s run this against pylint and see how much we’ve improved the results. For brevity, we’ll just show the first section below:


C:\Users\mdriscoll\Desktop>pylint crummy_code_fixed.py
No config file found, using default configuration
************* Module crummy_code_fixed
C: 1,0: Missing docstring
C: 4,0:CarClass: Empty docstring
C: 21,4:CarClass.get_weight: Empty docstring
W: 21,25:CarClass.get_weight: Unused argument 'this'
R: 21,4:CarClass.get_weight: Method could be a function
R: 4,0:CarClass: Too few public methods (1/2)

That helped a lot! If we added docstrings, we could halve the number of issues.

Wrapping Up

 

The next step would be to try running pylint against some of your own code or against a Python package like SQLAlchemy and seeing what gets output. You can learn a lot about your own code using this tool. If you have Wingware’s Python IDE, you can install pylint as a tool that you can run with just a couple mouse clicks. You may find some of the warnings to be annoying or not even really applicable. There are ways to suppress such things as deprecation warnings through command line options. Or you can use the –generate-rcfile to create an example config file that will help you control pylint. Note that pylint does not import your code, so you don’t have to worry about undesirable side effects.

At this point you should be ready to start improving your own code base. Go forth and make your code amazing!

Further Reading

 

  • PyLint official website
  • My article on PyChecker
  • PyChecker’s official website (a similar project to PyLint)
  • pyflakes – another similar project
  • Doug Hellman’s review of Python Static Code Analyzers from the Python Magazine
Pylint Python (language)

Published at DZone with permission of Mike Driscoll, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • How Agile Works at Tesla [Video]
  • Integrating AWS With Salesforce Using Terraform
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • What to Pay Attention to as Automation Upends the Developer Experience

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: