user

8 Tips to Improve Your Python Scripts Immediately

Introduction

Crista Perlton

Crista Perlton


LATEST POSTS

How Licenses Work with Chocolately 22nd March, 2024

How to Handle npm Dependencies with Lock Files 16th January, 2024

Python

8 Tips to Improve Your Python Scripts Immediately

Posted on .

Be honest. Have you ever opened a script, spent 30 seconds trying to understand it, then walked away because you couldn’t figure out what was going on?

Now be brutally honest, were you the original creator of that script?

Every day on teams around the world, team members are re-creating code that already exists.

There are TONS of articles outlining “Best Python Coding Practices” targeted towards Python projects/applications practices. But these typically require you to spend time investing in skills that take years to master.

This article will outline the 8 simple things non-developers can do to immediately improve Python scripts.

Our advice is:

1. Differentiate Your Scripts from Your Applications

In Python, there’s no clear line between Scripts and Applications, but identifying those differences internally is important. Scripts are much easier, simpler, and cheaper to create and maintain compared to applications. Without defining the difference internally, you run the risk of spending an application’s amount of effort on a simple script.

As a general rule, scripts are created by coders for coders. Scripts are often technically difficult and require training to understand. However, that doesn’t mean that scripts complete technically difficult executions. Scripts can do something as simple as opening a port or putting a computer to sleep.

Applications are created by developers for end-users and typically come with some sort of graphic interface. Applications often must follow business and technical processes and often go through much more rigorous and regimented testing, QA, review, etc. before they’re ever available for use.

The biggest difference is who uses them and the mentality behind their creation.

2. Split Your Scripts Up

The first way to improve your coding practices immediately is to stop overengineering your scripts. If there’s ever a point where you think “Oh this could be two separate scripts” then it probably should be two separate scripts. The more “features” you add to a script, the riskier it is to change – and the closer it becomes to an application.

Improving your Python code isn’t about creating a piece of code that’s bug-free or optimizing something to its limits. It’s about writing a script that all members of your team can understand, run, and modify. Adopting this mentality allows team members (today and tomorrow) to easily change and evolve alongside your team and organizational needs.

You may have been the original creator of a script, but you do not own it. Your company owns your scripts, and your company needs to be the keeper of them. I’ll say it once again for the folks in the back, you cannot be the sole person responsible for understanding how/why you made your scripts and how/when to use them!

3. Minimize Package Usage

Especially for your junior team members, scripts need to help get them up to your speed, not stall their progress. Less time spent trying to understand a script means more time spent on constructive learning and growth.

There are a ton of great PyPI packages available, but the more you use, the longer it’ll take someone else to learn and understand your script.

How do you keep things simple? Well on top of splitting scripts up, scripts should mostly be able to use the standard library and not require too many (if any) third-party packages. Packages like Colorama and JMESPath are convenient and add functionality to Python, but it’s less and less likely that junior engineers will know how they work.

Our advice? Stick with packages that are stable and that everyone on the team will be familiar with. Keep in mind, the better the package documentation, the easier it’ll be to train on.

When using third-party libraries, environment management (i.e. which packages and versions are installed) becomes important. Lots of packages mean lots of environment management. While it’s possible to package all scripts and dependencies and deploy that, that’s coming really close to an application and is in danger of getting complicated quickly.

4. Use Version Control

If you’re not already following it, your team needs to adopt version control for your scripts.

This doesn’t mean you need to jump into Git-based source control. There are much simpler tools available, and you’re probably already using them: SharePoint, OneDrive, and Dropbox are all fine options to get started. They’re much better than a network drive that’s backed up from time to time.

Version control can be used to roll back changes if things go wrong, and someone makes a bad edit. It also stores an audit of who made changes and when, and if you use these basic tools, it happens every time the file is saved.

5. Use Comment Headers

Scripts are company assets, so they should be maintained as long as possible. If you are constantly spending time writing new scripts, you may as well not be using automation and still be doing everything by hand.

Writing great comments definitely helps with script maintainability, but like writing great code, it can take a lifetime to master. There’s a much faster, simpler way to make a better script: comment headers. Here’s a quick example of the contents of a comment header:

This script leverages RESTCONF to updates the IP address on the interface.

Args:
interface_name (string): name of the interface to update
ip_address (string): new IP address
ip_netmask (string): new IP netmask

Example:
Set the IP for the two adapters after setting environment variables
for the username/password

$ export XEUSER=antprash
$ export XEPASS=ssp0i0y10
$ py restconf_setip.py GigabitEthernet1 172.23.4.28 255.255.251.0
$ py restconf_setip.py GigabitEthernet2 172.23.4.29 255.255.251.0

While there’s no real standard for what these look like, at an ABSOLUTE MINIMUM, you need to include a description and arguments to run the script. Examples are really helpful, too.

You don’t need to go overboard: just start by writing a sentence or two that describes the purpose of your script. Then add this as a comment to the comment header. Just try to keep in mind your audience and what they would want and need to properly understand and use your script:

  • Runners: people who read the script before they run it
  • Editors: people who are responsible for adapting and maintaining your script

Most scripts outlive their creators in an organization, and a great script is one that can change and it’s clear how to change it.

6. Use Docstring-style Comments

Instead of using “#” for all of your comments, you should switch to docstrings (i.e. “””) for comment headers, functions, and definitions. It’s a small change, but one that you and your future team members will appreciate later.

The most obvious immediate benefit is that you get multiline comments, and don’t need to start every line with a “#” symbol. But more importantly, docstrings provide a very easy and convenient way of associating documentation with Python modules, functions, classes, and methods. And best of all, when properly formatted, users can easily access internal help by calling the `help` function.

For example, here’s what “standard” comments look like:

# This script leverages RESTCONF to updates the IP address on the interface.
#
# Args:
# interface_name (string): name of the interface to update
# ip_address (string): new IP address
# ip_netmask (string): new IP netmask

And here’s the docstring version:

“””
This script leverages RESTCONF to updates the IP address on the interface.

Args:
interface_name (string): name of the interface to update
ip_address (string): new IP address
ip_netmask (string): new IP netmask
“””

And that’s it!

As an added bonus, if you format your docstring comments following popular conventions like Google’s Style Guide for Docstring Headers, other tools like Otter can then read your script and display a UI to help run it. This means you could use those comments to create an auto-generated, personalized GUI.

7. Use Logging Not Print

While you may find some arguments online, it’s our firmly held belief that teams should be choosing logging over print.

Logging allows users to easily see where and when a logging call is being made and you can categorize your logging based on four levels of severity. Print doesn’t offer any extra functionality or usability past putting words onto the screen. It’s a small change to how you write your code, but it is a game-changer for your Python codebase.

print ("An error occurred. Missing Input")
-- vs. --
logging.error ("Missing Input")

Like using print(), logging() will help you troubleshoot scripts. But unlike print(), logging will show you where and when a logging call is being made from. Logging lets you control which severity level to display on the console, which severity level to save in a text file, or do both!

Other Python modules use logging as well, and you can categorize based on whether the messages are from your modules, your scripts, or third-party modules.

Not that you’ll start doing any of those things right away, but as you get more experienced and advanced in your scripting practices, you’ll come to appreciate that your old scripts used logging over print.

An added bonus of logging is external Infrastructure management tools, like Otter, can read and collect the various output streams from Python to create permanent records that can be used to analyze scripts more efficiently than simply scrolling through hundreds of lines of output.

8. Improve Your Error Handling

Code your scripts with this mantra in mind: “Everything I write will fail.” Failures could be something as simple as not being able to find “cute-otters.jpg” or something a bit more serious, such as a setting not applying correctly, leading to a bunch of misconfigured servers.

Python supports a simple but powerful Try/Except statement that will try to execute a command and catch any errors that occur. For example:

import logging
try:
   1/0
except ZeroDivisionError:
   logging.warning("Divide by zero error")
except Exception:
   logging.critical("Other exception")
finally:
   logging.info("Cleaning up...")

The biggest benefit you’ll get from using this today is the ability to log additional information about the error, or even continue if the problem is recoverable.

Another improvement you can start today is the raise statement. It works almost the same as printing some messages and then using sys.exit() when things go wrong.

print ("Error: The .BAML file had an unexpected format.")
sys.exit(-1)

-- vs --

raise Exception("The .BAML file had an unexpected format.")

However, the raise statement will make it easier to handle the error with try/except – particularly if you’re having one script call another script. It also makes the script much more readable by clearly defining what will happen in specified scenarios.

Improving Code Quality Through Better Practices

Simple code is better code. Start simplifying your code by splitting up your current scripts and practicing your commenting. Truly improving and overhauling your Python codebase will take years to get right, but using these 8 easy tricks, you can immediately improve your Python scripts.

These tricks are just the beginning of what it takes to become a Python master. To learn more, sign up for our Effective Package Management in Python guide.

Crista Perlton

Crista Perlton

Navigation