Python Coding Standards

“Visualizing logical concepts can aid in understanding them effectively”

Photo by Clément Hélardot on Unsplash

Introduction:

This article does not aim to teach you Python programming language. The target is to teach you how to visualize the code execution and how to write code in a standard company format. Every company or organization has its own way of maintaining the standard and structured code. Let’s learn some of those.

You can follow any YouTube channel or Website for learning Python,

  1. Geeks for Geeks
  2. w3schools
  3. Tutorials Point

Visualization Representation of Code Execution:

It is essential to consider visualizing each logical statement individually, line by line. But the question is “How can I visualize python code execution?

  1. Using a Debugger: Python provides built-in debugging tools such as “pdb” and “ipdb” that allow you to step through your code line-by-line and inspect variable values as the code runs. This can be a useful way to understand how your code is working and identify any errors.
  2. Using a Visual Debugger: There are also several visual debuggers available for Python, such as “PyCharm”, “Visual Studio Code” etc. These tools provide a graphical user interface that makes it easy to inspect your code. They also typically include other features such as breakpoints, watches, and call stacks.
  3. Using a Profiler: Python provides built-in profilers such as “cProfile” and “profile” that can be used to measure the performance of your code and identify any areas that may be causing it to slow down. There are also other performance analysis tools available such as py-spy which allows you to get a visual representation of the execution of your code.
  4. Using a Tracer: A standard library trace module allows you to trace the execution of Python code and save the output to a file. The trace output contains information about function calls, including the function’s name, the arguments passed, and the return value.

For me above all, the simple answer is “Using Python Tutor”, an online Python compiler and debugger tool.

Let’s visualize a Python program to reverse a Linked List. The link to the Python program is here.

Image by Suryakant Soni

As you can observe in a visual representation of the Python program shows you,

  1. Explanation of the definition and usage of class, method, and object within an interpreter.
  2. Examining the process of allocating memory for each object within the interpreter.
  3. Step-by-step or Line-by-Line execution of the underlying business operations
  4. Observing the working of object initialization in memory, and so on.

Guidelines for Maintaining Code Clarity:

Developers usually use to spend much time reading and understanding any code rather than developing it. So it is more crucial to write Understandable, Maintainable, Scalable, and Reusable code.

Coding Standards should be achieved in many possible ways,

  1. The exception should be handled properly in each and every layer.
  2. There should be a proper separation between the business layer and the service layer.
  3. Every API should be authorized with the proper token.
  4. The logger should be implemented into every block of code.
  5. The memory allocation of unwanted variables and literals should be minimized.
  6. PEP8 standards should be followed properly and hardcoding should be avoided.
  7. Unit testing should be enforced on the development of every module.
  8. The naming convention of each variable/literal should be declarative and pronounceable.
  9. Comments/Docstring should be provided for each module/function inside a Class.
  10. The folder structure should be maintained properly within the layer.
  11. Avoid adding redundant context to the variables.

Let’s elaborate and learn more about the above contexts.

Exception Handling:

In Python, an error or exception is something that crashes the program or produces incorrect results. Exception handling is a way to deal with these errors and to continue running the program, rather than stopping it entirely.

def fetch_header_content(user_role):
"""
This method is to fetch header data for required user_role from the database
:param user_role: User Roles
:return:
"""
header_content_list = []
try:
logger.info("Fetch header content for the table")
if user_role:
header_content_list = portgres_obj.execute_query(
query=QUERY_HEADER_CONTENT.format(
user_roles=user_role))
except Exception as err:
logger.error("Error occurred while fetching header content for the table")
raise Exception(str(err))
return header_content_list

You can also use the “finally” block, which contains code that will always be executed, whether an exception is raised or not. This block is useful for cleaning up resources, such as closing a file or a database connection to ensure no memory leak, which should be done regardless of whether an exception was raised.

You can read more about “try-catch” read here.

Service Layer & Business Layer:

There should always be a separation between the service layer and the business layer, but first What are the service layer and business layer?

Service layer: The Service layer is the layer responsible for handling the API request.

Business Layer: The Business layer is the layer responsible for handling business logic

Utility Layer: The utility layer is responsible for keeping all DB utilities like portgres_utility.py, elasticsearch_utility.py, mongo_utility.py, etc

Exception Layer: The exception layer is responsible for catching all the database as well as code exceptions

Logger Layer: The logger layer is responsible for creating a logger for code that logs each exception or information while running the code.

PEP 8 (Python Enhancement Proposal):

PEP 8, sometimes spelled PEP8 or PEP-8, is a document that provides guidelines and best practices on how to write Python code. The most common rules are as follows,

  1. The class name should be in CamelCase (PostgresDBUtility)
  2. All the variables or literal should be in snake case and all lowercase (user_name or user_roles)
  3. The function names should be all lowercase and in snake case (def fetch_record())
  4. All common constants should be in uppercase and in snake case (PI = 3.14159)
  5. Import statements should be on separate lines and followed by Class
  6. Multiple statements should be avoided in the same line
  7. Trailing whitespaces should be avoided in the code

For proper indentation practice in your PyCharm first, select all code using “CTRL + A” and second arrange indentation using “CTRL + ALT + L”. PyCharm will automatically arrange all your code with proper indentation.

To read more about PEP8 standards, read here

Naming Conventions:

Some of the points are already covered in the PEP 8 section, but apart from those you should keep in mind that it is always better to use long, declarative, and pronounceable.

Example: 1

# Worst Practice

p = {"some_param_key": "some_param_value"}
r = requests.get("some_url_link",p)
# Best Practice

header_parameter = {"some_param_key": "some_param_value"}
header_response = requests.get(url="some_url_link", params=header_parameter)

Example: 2

# Worst Practice

n = "Google Application"
c_t = 1621535852
c_usr_nme = "some_user_name"
# Best Practice

application_name = "Google Application"
created_timestamp = 1621535852
client_user_name = "some_user_name"

Example: 3

You should never use any magic numbers in your code. Like,

# Worst Practice
# What is 200? Some magic number?

for i in range(0, 200):
# Best Practice

PACKET_COUNT = 200
for each_package_counts in range(0, PACKET_COUNT):

Comments/Docstrings:

The purpose of a docstring is to provide meaningful documentation for the code so that others (or yourself when you come back to the code later) can understand how it works. It is a Best Practice to include a docstring for all modules, functions, classes, and methods using “”” triple quotes “””.

Image by Suryakant Soni

Example:

# Worst Practice
def fetch_header_content(user_role):
pass
# Best Practice
def fetch_header_content(user_role):
"""
This method is to fetch header data for the required user_role from the database
It returns the list of all the header contents retrieved from the database for a particular user role
:param user_role: User Roles
:return:
"""
pass

Class/Object:

Always try to maintain a good habit of writing any piece of code using Class and Objects in python. A Class is like an object constructor or a “blueprint” for creating objects.

Example:

# Worst Practice
def fetch_header_content(user_role):
pass


def fetch_site_content(site_url):
pass
# Best Practice

class SiteContentClass(object):
"""
This class is responsible to get site data
< More information about the class >
"""

def __init__(self, site_url, authentication_key):
self.site_url = site_url
self.authentication_key = authentication_key

def fetch_header_content(self, user_role):
"""
This method is to fetch the header content from the
<table_name> in required user roles
: param user_role:
:return: list of user roles
"""
pass

def fetch_site_content(self, site_url):
"""
This method is to fetch the required site content
: param site_url:
:return: list of object in required site
"""
pass

Structures of Directory & Files:

In Python, the structure of a project can vary depending on the complexity and purpose of the project, but there are a few common conventions that can be generally followed. A typical project structure might look something like this,

Image by Suryakant Soni

Let me describe each one of the above,

  1. application.conf: All the DB configurations, should be written in the ‘application.conf ’ file
  2. logs: All the logs will be stored in the logs folder with <projectname_ddmmyyyy.log> format
  3. app_configuration.py: All the constants should be stored in the “app_configuration.py” file. We can read configuration from “application.conf” using the configparser library
  4. app_constant.py: All the service handler endpoints should be stored in the “app_constants.py” file
  5. service: All the API requests should be handled in the service layer of the application
  6. handler: All the business logic should be handled in the handler layer of the application
  7. logger: The logger logic should be handled in the ‘logger.py’ file
  8. exception: All the database and code exceptions should be maintained in the “exception_codes.py
  9. utility: The utility for any database should be kept in the utility folder
  10. templates: The re-usable templates should be maintained in separate files in templates folder
  11. Every code should have aREADME.md file, in which all the descriptions of the code should be mentioned
  12. The libraries which are used in the particular project should be mentioned in the requirement.txt file

Code Analysis Tools:

There are several code analysis tools available for Python, depending on your specific needs. Some popular options include

Image by Suryakant Soni
  1. Pylint: Pylint is a popular code analysis tool that checks for errors, coding standard violations, and other issues in Python code. It is highly configurable and can be integrated with a wide variety of IDEs and text editors.
  2. Flake8: Flake8 is another code analysis tool that combines the functionality of PyFlakes, pycodestyle, and McCabe. It checks for style issues, such as PEP8 violations, and also looks for other errors and issues in your code.
  3. Mypy: Mypy is a static type checker for Python. It checks your code for type inconsistencies and helps you to find and fix type errors before your code is run.
  4. Bandit: A bandit is a tool designed to find common security issues in Python code. It looks for issues such as SQL injection, cross-site scripting, and insecure use of cryptographic functions.
  5. Pytest-benchmark: A pytest plugin for benchmarking code, It can be used to compare the performance of different implementations of the same algorithm, and see how they scale as the input size increases.
  6. Pytest-cov: A pytest plugin to measure the coverage of python code while running unit tests

I personally suggest you should use “Pylint” after developing your code. Pylint displays a global evaluation score for the code which should always be greater than 8.0. You can use these tools individually or integrate them into your development workflow to automatically check your code as you write it.

Unit Testing:

Unit testing every module within each layer of the application should always be a priority before considering the quality of the code. Only after thorough unit testing has been completed should the code be pushed to the GIT repository for further integration.

There are several libraries and frameworks available for writing and running test cases in Python, such as unittest, pytest, nose, and doctest. Let us observe a simple example to test your code using “pytest”.

Image by Suryakant Soni

We can run this program using the command “pytest testing_python_code.py” and you will get the error of your code like this

Image by Suryakant Soni

If your code meets the standards and produces the expected output according to the test case, the correct code should be similar to the following.

Image by Suryakant Soni

The testing results for your code are displayed below. Once it passes the unit tests, it can be integrated and pushed to GIT.

Conclusion:

Creating clear and efficient code can be challenging as there is no specific formula to follow. I have observed and examined various coding standards and general principles that can assist you in improving your code.

One of the key suggestions is to maintain consistency and aim for code that is simple and easy to test. If you find that your code is difficult to test, it is likely challenging to utilize as well.

If you have reached this far, thank you for reading this blog, I hope you found it insightful 😃. Give us a follow for more content on technology, productivity, work habits, and more!

--

--