Skip to main content
Test Double company logo
Services
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say Hello
Test Double logo
Menu
Services
BackGrid of dots icon
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
Cycle icon
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say hello
Developers
Developers
Developers
Software tooling & tips

4 tools for your Python developer toolkit

Unlock the full potential of Python with these game-changing tools. From pytest-sugar to ptpython, discover how to enhance your coding efficiency and have a little fun.
Kyle Adams
|
January 7, 2024
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

It feels like—after three decades—the Python world is experiencing a renaissance, both in tooling and in libraries. It’s an exciting time to be a Python developer.

‍We’ve seen exciting libraries like Pydantic and FastAPI picking up steam, which is fantastic.

That said, there are also some smaller utilities that are gems in their own right. Some, like pytest-sugar, can be dropped into a project with minimal fuss. Others, like ptpython, can be used by an individual on a team without impacting the team.

Here are four can’t-live-without Python tools that I’ve recently added to my dev utility belt because they make me a faster developer (and they’re doggone fun to use):

4. ptpython

Website: https://github.com/prompt-toolkit/ptpython

Installation: python -m pip install ptpython, Python 3.6+

Ptpython is what the built-in Python REPL ought to be. Just take a look at these features!

Syntax highlighting

Screenshot of the syntax highlighting in ptpython
   Syntax highlighting

Autocompletion

Screen capture of autocompleting the capitalize function on a string in ptpython
   Autocompletion

Autoindentation

Watch ptpython automatically indent the body of this class; I didn’t have to manually add tabs or spaces!

Screen capture of automatic identation for a class block in ptpython
   Autoindentation

Multiline editing

In this example, I forgot to include the age attribute when I initially defined the class. I hit the up arrow once and now I can edit the entire multiline block of that particular class.

Screen capture of hitting the up arrow once to edit an entire class block at once in ptpython
   Multiline editing

Syntax errors

Ptpython will catch syntax errors before you execute the line, giving you a chance to go back and fix them before execution. And yes, it works with multiline blocks.

Screen capture of being able to fix a syntax error before executing a line in ptpython
   Syntax errors

I haven’t even gotten into Emacs/Vi modes, IPython compatibility, displaying docstrings and function signatures, running shell commands without leaving the REPL, and host of other features. The next two tools are the peanut butter to ptpython’s chocolate, so install it and get ready for even more fun!

3. devtools, rich, and icecream

Website: https://python-devtools.helpmanual.io/

Installation: python -m pip install devtools, Python 3.7+

Website: https://github.com/Textualize/rich

Installation: python -m pip install rich, Python 3.7+

Website: https://github.com/gruns/icecream

Installation: python -m pip install icecream, Python 2, 3

The next tool is a three-fer: devtools, rich, and IceCream are all great libraries and which one I reach for just depends on how I’m feeling at the moment. They all make printing complex data structures so much nicer than Python’s pprint. They also have more tricks up their sleaves than just pretty printing. Let’s dig in…

devtools.debug()

debug is like print after a good night’s sleep and lots of coffee

The devtools Usage page has a colorful-but-apt description of what debug does. It will pretty print as many variables as you can throw at it, along with the file name, line number, and function where debug is being invoked.

Screen capture of printing out both a complex—nested dictionaries and lists—data structure as well as the returned value from a function call using devtools.debug()
   debug()

Additionally, debug returns what you pass into it, meaning you can insert it into your code without changing functionality:

Screen capture of devtools.debug() returning the class passed into it, allowing the variable assignment to happen as expected
   inlined debug()

devtools.debug.timer()

You can also use the timer function to do basic timings on operations:

Screen capture of devtools.debug.timer() timing a longer-running operation
   debug.timer()

devtools.debug.breakpoint()

Finally, you can use debug.breakpoint() to invoke pdb:

Screen capture of devtools.debug.breakpoint() invoking pdb
   debug.breakpoint()

rich.print()

Similar to devtools.debug(), rich.print() is a better pretty printer. Unlike devtools.debug(), which is solely focused on debugging, rich.print() supports a slew of formatting options, such as shortcodes (including emojis).

Screen capture of rich.print() formatting shortcodes and emojis
   rich.print()

rich.inspect()

rich.inspect() is a nice tool for digging into variables; it shows the type, the contained values, and optionally methods, private, and dunder attributes. Note: if “dunder” is a new term for you, it refers to attributes with double underscores around them, like __init__; “double underscore” gets tiresome to say, so you’ll frequently see that shortened to “dunder” in the Python world.

Screen capture of rich.inspect() showing more details about an object
   rich.print()

icecream.ic()

ic() is pretty similar to the other two libraries but with the added advantage that it’s even faster to type!

Screen capture of icecream.ic() printing out basic data
   icecream.ic()

It will print both the variable name and its value, with syntax highlighting.

Screen capture of icecream.ic() printing out a complex dictionary
   icecream.ic()

Like devtools.debug() it’ll return what you passed in, so you can inline it in your code.

Screen capture of icecream.ic() printing out a class; the instance is also passed to a variable, which is then passed to another ic() call to print the name attribute
   icecream.ic()

One additional neat trick is that you can scatter it throughout your code like debugging breadcrumbs and it’ll inspect itself, leaving you with a trail of exactly which lines in the code were triggered:

Screen capture of icecream.ic() printing out a trail through multiple functions and conditionals
   icecream.ic()

2. pytest-sugar

Website: https://github.com/Teemu/pytest-sugar

Installation: python -m pip install pytest-sugar, Python 3.8+, pytest 6.2+

pytest-sugar is a drop-in (automatically activated) plugin for pytest. It does several things to make your tests look and work better:

  • Errors are reported immediately; no waiting to see what broke
  • A progress bar visualizes how far you’ve progressed through the suite
  • Colored summary report

Here’s a test suite without pytest-sugar:

Screen capture of a test suite, with some failures, using default pytest formatting
   Without pytest-sugar

And the same test suite with pytest-sugar:

Screen capture of a test suite, with some failures, using pytest-sugar's formatting
   With pytest-sugar

1. Ruff

Website: https://docs.astral.sh/ruff/

Installation: python -m pip install pytest-sugar, Python 3.7+

Ruff is an extremely fast Python linter. In addition to its speed, I also appreciate its sensible default settings and large ruleset.

Linting in Python is worth its own blog post, so I’ll try to summarize here. The question, “what linter should I use for Python?” always felt fraught with uncertainty and complications. I’ve seen many projects end up with autopep8, flake8, pylint, bandit, and isort and nobody knows which are still used … or even what they’re used for.

Ruff replaces them all.

It’s hard to understate just how little work we’ve had to do to switch to Ruff at my current client: we just swapped the dependencies out, deleted all the non-Ruff configuration, and were good to go. We started migrating to Ruff when we upgraded to SQLAlchemy 2.0 and ran into a bug that caused our pylint runs to be unbearably slow. The bug is now fixed as of pylint 3; however, our switch to Ruff was so easy that we didn’t need to wait around for that fix to land.

As Ruff matures, we continue to replace tools. The most recent swap was pulling bandit for Ruff’s flake8-bandit ruleset. We’re keeping an eye on the Ruff Formatter, and it seems likely that we’ll be replacing Black soon. (Black is another tool I love, and it would be on this list if it weren’t for Ruff moving towards feature parity.)

BONUS: VS Code Extensions

Because you made it this far, I’ll throw in two recently-discovered, favorite VS Code extensions:

indent-rainbow

Makes your indent levels both pretty and easy to read!

Screenshot of indent-rainbow shading different indent levels different colors in a JSON document
   indent-rainbow

gitmoji

Spice up your commit messages with gitmojis, because every commit log should be as beautiful as FastAPI’s.

Screenshot of FastAPI's commit log with gitmoji commit messages
   gitmoji

‍

Want to continue the conversation about Python tooling? Join our N.E.A.T. community or if you’re already registered, head on over to the forum to talk Python tool tips!

Related Insights

🔗
14 tools every Ruby developer will love for performance and debugging
🔗
Code generation tools are easy to start, but hard to master
🔗
Mastering automated refactoring tools: A practical guide

Explore our insights

See all insights
Developers
Developers
Developers
C# and .NET tools and libraries for the modern developer

C# has a reputation for being used in legacy projects and is not often talked about related to startups or other new business ventures. This article aims to break a few of the myths about .NET and C# and discuss how it has evolved to be a great fit for almost any kind of software.

by
Patrick Coakley
Leadership
Leadership
Leadership
Turning observability into a team strength without a big overhaul

By addressing observability pain points one at a time, we built systems and practices that support rapid troubleshooting and collaboration.

by
Gabriel Côté-Carrier
Developers
Developers
Developers
Why I actually enjoy PR reviews (and you should, too)

PR reviews don't have to be painful. Discover practical, evidence-based approaches that turn code reviews into team-building opportunities while maintaining quality and reducing development friction.

by
Robert Komaromi
Letter art spelling out NEAT

Join the conversation

Technology is a means to an end: answers to very human questions. That’s why we created a community for developers and product managers.

Explore the community
Test Double Executive Leadership Team

Learn about our team

Like what we have to say about building great software and great teams?

Get to know us
Test Double company logo
Improving the way the world builds software.
What we do
Services OverviewSoftware DeliveryProduct ManagementLegacy ModernizationDevOpsUpgrade RailsTechnical RecruitmentTechnical Assessments
Who WE ARE
About UsCulture & CareersGreat CausesEDIOur TeamContact UsNews & AwardsN.E.A.T.
Resources
Case StudiesAll InsightsLeadership InsightsDeveloper InsightsProduct InsightsPairing & Office Hours
NEWSLETTER
Sign up hear about our latest innovations.
Your email has been added!
Oops! Something went wrong while submitting the form.
Standard Ruby badge
614.349.4279hello@testdouble.com
Privacy Policy
© 2020 Test Double. All Rights Reserved.