How to Solve Annoying IndentationErrors and TabErrors in Python on Replit (or Anywhere Really)
So there I was.
Alternating between coding and listening to old Led Zeppelin tracks I totally haven't already jammed to a million times, considering that maybe I should've picked something more responsible and reliable for a career than software development.
You know, something to really impress mama... Something like being a rockstar like Jimmy Page πΈπ€. He's got a pretty stable lifestyle, right? I could probably be him.
When all of a sudden, an evil error pulled me perniciously down from the cloudy apogee of my daydreams, reminding me of my other, more mundane, yet still flagging dream of being a code superstar like Taylor Otwell.
It was that nightmarish and nefarious error, the defeat of which has become a proper rite of passage for all up-and-coming pythonistas, and who has for decades deviously drawn the ire and dread of Python devotees the world over.
It was totally a TabError
I've recently been coding in Python on Replit.
The two are a charming duo, to be sure. But I'd be willing to bet that just about anyone, on or off Replit, that uses Python (or Ruby probably) has run into a situation I like to call "tab hell."
Even if you don't use tabs, I'm gonna call it that because it sounds catchier than "indentation hell" or "space hell"β although tbh that last one sounds vaguely cyberpunk/horror π€
This applies whether or not you're using tabs or spaces, and whether or not Replit is your main editor. I'm pretty sure it started to happen when I started getting cocky and trying to use code to generate code file boilerplate for my mini MVC framework.
I also stupidly altered the Replit tab settings halfway through the project, being the Neanderthal that I am. So to be clear, it was not due to a wart that Replit or Hacker's Keyboard has.
It was, as grandma used to quip with a smirk, "the operator."
Not to fear! Polydorkic is here π¦Έ Or maybe I should dub myself Polydorkus
π
I promise we will get to the bottom of this. All examples will intentionally be easily accessible if you code on mobile like I sometimes do; otherwise, if you're on desktop then this will be even easier for you. In any case, this solution is probably a handy tool to add to your toolbox.
But What About tabnanny
?
True, Python does come preloaded with that tabnanny
thing. My first experience with it was... neat. But not the π― % solution I was looking for.
Here is a screenshot of an error similar to the original one I generated:
Okay, let's give tabnanny
a shot. Here's an example of how to use tabnanny
on Replit:
Alright, so let's try it on that original problem. Here's the output:
Hmm.
Not very helpful in my opinion. I'm not personally sure that tabnanny
adds an immense amount of value on top of the default errors that Python already spits out. Adds a lot of cuteness though π
The problem in my view is that I don't just want to know what line the IndentationError
is on. To solve the problem I have to contrast the problematic tab or space location with the rest of the file. How do we do that? Because the whole point of using such a debugging tool is ostensibly that it's commonly difficult to accurately evaluate such problems with a glance of the naked eye.
I knew better (just barely) than to whip out a quick find-and-replace off the top of my head and risk mangling half my codebase. My first solution was to write a small utility that reads the contents of a specified .py
file and prints it to the console. That ended up being the solution, but with an additional step required.
Tabby_Poppins
is supercalifragilisticexpialidocious
Before I explain it, here's the REPL (feel free to use this in your own projects):
So the Tabby_Poppins
tool basically prints out the contents of the whole file to the console (unlike tabnanny
which just prints out the offending line without context). Additionally, like the tabnanny
tool, instead of rendering the tab and newline characters it explicitly declares their locations with \t
and \n
. So you can easily contrast where an actual tab character was inserted on one line and, say, spaces on another line.
Let's see what it the Tabby_Poppins
strategy has to say about my original error:
AHA.
So the problem is actually that an explicit tab character was used on one line before table
, and spaces were used on the next line before relations
. How that happened is my code boilerplate generator tool that I wrote generated the original file with an explicit \t
character, but my Replit editor settings (shown below) were set so that the tab key results in spaces, NOT a literal tab character. In python, there of course needs to be consistent indentation practices within a file so that when it is parsed the parser knows how to tokenize it properly.
Contrast the original Tabby_Poppins
output with the output now that I was able to pinpoint and fix the issue:
It pays to note that with my setup, using Replit in the Firefox Mobile web browser on Android with the Hacker's Keyboard, it turns out there is a difference between hitting the return key so the editor auto-indents the next line and simply hitting tab with the cursor at the beginning of a line. That detail isn't that important; the really important thing is that I was able to identify that inconsistency with this debugging approach and adjust it accordingly.
Because really, python doesn't care as long as your indentation is consistent in a file.