Pythonic pinpointing
I just noticed a principle, that I've been practicing for years.
Didn't even realize I was doing it, for a long time. But it's beneficial.
This principle applies whenever you use a "try" block:
- try:
- resp = requests.put(API_URL, json={"id": user_id})
- except ConnectionError:
- logging.critical("Cannot PUT to url %s for user ID %d", API_URL, user_id)
- task_queue.add_task(user_id, resp.json()["next_task"])
The principle:
Always put as few lines of code inside that "try" block as you can.
If you can put ONE just line of code in the "try" block... Then put one line. Everything else goes outside that block.
If it's literally impossible to do what you need with one line of code inside... then you can put two. Or if it's impossible to do with two, then three.
Get the idea?
What this does is prevent bugs from HIDING from you.
Because if some line of code is "protected" by a try block, and it unexpectedly raises the caught exception...
Then it can COMPLETELY mislead you on what went wrong.
Imagine you do this instead:
- try:
- resp = requests.put(API_URL, json={"id": user_id})
- task_queue.add_task(user_id, resp.json()["next_task"])
- except ConnectionError:
- logging.critical("Cannot PUT to url %s for user ID %d", API_URL, user_id)
Except unbeknownst to you, this task_queue object uses the requests module under the hood, interacting with some task-queue microservice.
And that microservice goes down. Raising a ConnectionError.
Now your log files are lying to you, and it's your fault, because you put two lines of code in that "try" block, instead of one.
So avoid this class of horrible, baffling bug, and pinpoint your "try" blocks from now on.
That's today's tip to save you from endless hours of teeth-gnashing suffering. You're welcome!