Exception Handling With Function Generators

Stephen Gruppetta spoke at our PUG a few months ago. He also writes on SubStack. Here is an article he wrote on your subject du-jour with links to other material which will likely be of-interest:-

Pay As You Go • Generate Data Using Generators (Data Structure Categories #7)

Generators • Part 7 of the Data Structure Categories Series

Stephen Gruppetta


Markdown tutorial - specific page to repeat answer. Rest of site will tell you more…

I am using Learning Python, 5 Edition 2013 by Mark Lutz (covers up to Python v3.3). It covers a lot of topics and is very comprehensive. Unfortunately, it has been ten years since he last published an updated edition. All of his prior editions were revised every ~4 years.

Hopefully someone will pick up where he left off and follow up with a 6th Edition with updated material for Python v3.12 (one can only hope).

In case you wonder why

1 Like

Thanks for highlighting these. I think most of these arguments are quite poor, frankly (there’s in particular a habit of citing PEPs and then criticizing the corresponding feature, ignoring arguments made in the PEP to preempt the criticism) although there is certainly some agreeable and interesting perspective. The author’s general idea of how changes get introduced to the language, seems completely at odds with the experience one gets reading the Ideas category :wink: But I’ve had it in mind to write about the evolution of Python and it will be interesting to incorporate some of these views.

Yeah, I flipped through those arguments, and came to the conclusion that, while he might have some good reasons for disliking certain features, he’s coming across so much as a “get off my lawn” complainer that any good arguments he has are getting swamped.

The Red Queen explained the nature of upgrades to Alice quite aptly:

… it takes all the running YOU can do, to keep in the same place.
If you want to get somewhere else, you must run at least twice as
fast as that!

(Through the Looking-Glass and What Alice Found There)

Even if you don’t like ALL of the changes, you can’t just stay where you were - you’re actually going backwards. But what he’s doing is muting his own voice. Instead of creating an article about Python and then saying which features are good and which are not, he simply creates a whine page - or at least, that’s what it comes across as - with a list of grievances. Not constructive, as the only take-away is “stick to the old version of Python, it was better”.

1 Like

Things are getting serious(?) when @Rosuav starts quoting Lewis Carroll!

It is a frustrating process to be an author and have to regularly (annually?) go through all of one’s material checking to see if updating might be necessary. In the case of a book-author, the idea of a new edition being published annually is unlikely to be economic - conversely, the more updates there are to the language the faster one’s text ‘degrades’. That said, in the case of a trainer, best-practice is to review the material prior to every delivery - sometimes improving the presentation (based upon observation of previous trainees’ behavior/results) and sometimes updating to reflect Python. Upon consideration, this is not substantially-different from a professional programmer maintaining code and taking the opportunity to upgrade a system to the latest Python (and packages) whilst performing some client-demanded task - which may include refactoring to take advantage of ‘new’ coding constructs.

An irony in the argument is that type-hints are, technically-speaking, not part of “Python”. A script can be written and executed quite happily without any type-checking whatsoever. It is perfectly valid Python - whether it is acceptable to Code Review is another matter. Accordingly, the aforementioned book (which has been thoroughly-recommendable) could remain largely-valid for much longer, without any need to update it to include typing ‘advances’. However, my experience has been that trainees appreciate sample-code and illustrations with typing, because it removes a whole ‘level’ of thought necessary for comprehension (or confirms mental-models). Accordingly, I’ve been recommending such use of type-hints for the last couple of years (at least).

Yes, there is something of an impression that some language-updates have been less applicable than others. This could be some sort of ego-trip amongst core-developers/contributors. However, it seems more likely a symptom and characteristic of a language which has grown ‘up’ and is now ‘growing out’. Even a casual observer (who has been ‘around’ for some time) will note that Python is being applied in an ever-wider range of application-areas. How many used PyTorch (et al) three?five years ago - compared to Python’s use in AI today? The growth of Python’s use in “Data Science”. Python in the browser. Matrix operations without needing to import NumPy (or…). The list goes on… It’s a brave, new, world…

Really? I swear, some days it feels like I quote six different books before breakfast…

That is very true, and I fully understand that documents, once written, can become almost instantly dated. But with a well-designed and stable language, very little will become WRONG. A program designed for Python 3.4 will largely be valid for Python 3.12, with only a handful of exceptions - most of which are things you wouldn’t want to be doing in early teaching anyway. So for the most part, it’ll go from “this is best practice” to “this is a conservative choice, do this for compatibility with older versions” to “this still works, but there are other ways now”.

Obviously this doesn’t apply to everything, but Python does try to make it very clear when that isn’t the case (eg asyncio in Python 3.4, which was specifically flagged as provisional - it did indeed change quite a bit after that).

Yeah, and the optional nature of those hints is extremely helpful. Notably, type hints have been syntactically supported since Python 3.0, so even if you added them early, they wouldn’t BREAK anything. (Though if you’re importing certain things from typing, you might need a shim to make sure they work.)

Maybe, but I doubt it. Here, let’s do a bit of an exercise. Everyone who thinks that there’ve been unnecessary features added, go through the What’s New What’s New in Python — Python 3.12.1 documentation for Python 3.10, 3.11, and 3.12, and identify everything that you think is unnecessary. I think we’ll all pick out different things, and the more developers you ask, the less likely that any feature will be deemed unnecessary by everything. For example, I don’t do much with type hints, so a lot of the advanced features there are quite useless to me, and I wouldn’t be teaching them; but I know they’re of great value to other people.

Recommend eating earlier…

Actually, I think “Alice” would be quite at home with the bug-bear that you’ve provoked my curiosity to re-visit. (I’ve re-built my m/c and the new OpSys (version) installed v3.12, and thus PEP-701 and ‘advanced F-strings’).

The “bug-bear” is work-arounds! Sometimes, we want to do something but our mental model (however [un]reasonable) differs from Python’s official syntax and semantics. Sometimes we come-up with an implementation/model/pattern before Python enables same, eg yield from. Later versions may address same. In which case, we may have to ‘undo’ a work-around because (a) it is no-longer relevant, and (b) may well confuse more-modern readers/maintainers. Can you sense my curmudgeonly-ways surfacing?

One of these is the reason I mentioned F-strings. Personally, I think they’re great and use them all the time! (although, I’d have liked strings to have been updated, rather than the “F” prefix) I’ve not had much use for the ‘debug form’, although every now and again…

My [insatiable] curiosity led me to read the What’s new re-read both PEPs (498 and 701), and to note formal recognition of what I had previously suspected (but evidently not consciously-comprehended), that even after the PEG-Parser was introduced, string-formatting and its sub-language continued to be governed by its own parser/different rules.

As my eye-sight deteriorates (much like everything else) I find horizontal white-space more-and-more helpful. Accordingly, I add spaces on the inside of brackets, eg def f( a, b, c, ) unless they are actually empty (although some fonts make [] look like a single box rather than two characters - (a) “ligatures”, (b) flashback to old(?) MS-Windows font-flailing (which OpSys I no-longer use in any version).) The added space is so much easier (for me) to scan than def f(a,b,c).

Accordingly, when adding formatting information to identifiers/values within F-strings I have wanted to type:

>>> import datetime
>>> date = datetime.date(1991, 10, 12)
>>> F'{ date } was on a { date:%A }'

but this syntax was rejected by Python <3.12.

In v3.12 it works! So I was ‘happy like a bunny’, aka “The White Rabbit”, except that now my “oh dear, oh dear” came from the contemplation of the work involved, were I to sit-down and methodically update all code with historic F-string formatting!

Unfortunately, further curiosity led me (back) to “The Mad Hatter” and the feeling that perhaps time had not moved-on quite as I had hoped:-

One of the purported advantages of the new, improved, F-strings is the ability to nest expressions. A favored example notes that both the value and the presentation-format are computable. In this vein, one of my favorite exercises specifies scanning the columns of a table to customise each presentation by allowing sufficient horizontal-space for the widest content in each column, ie computing the presentation-format. The PEP enables combination of both computations in one F-string. Readability (IMHO) suggests they are better separated. However, with such a spec in-mind, back to F-string syntax:

>>> import decimal
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal( '12.34567' )
>>> F"Result: { value:{ width }.{ precision } }"


  • yet in v3.12 it should work - according to the re-working of my mental-model, per the earlier, trivial example of my preferred layout! Where is the problem? Here is a process of elimination:
>>> F"Result: { value:{width}.{ precision } }"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid format string
>>> F"Result: { value:{width}.{precision} }"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid format string
>>> F"Result: {value:{ width }.{ precision }}"
'Result:      12.35'
>>> F"Result: { value:{ width }.{ precision }}"
'Result:      12.35'
>>> F"Result: {value:{ width }.{ precision } }"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid format string

Thus, it is that space between the last nested-expression and the outer-expression/closing-brace which causes an objection. So much for the (lack of) significance of white-space. Also, my dreams have not come true (sob).

Back to the discussion-topic (as it has transmogrified): those are two reasons why Python-updates are going to feed my curmudgeonly-soul rather than my Python-enthusiast personality. ???

OK, enough with the quotations and citations - surely it’s time for lunch?
(even [a] tea would go down well…)