Can you elaborate on the part "Lisp as a great code generating language"? Just curious. I tried to learn Scheme for SICP but then switched to the Python version.
Lisp's big strength is that since the program itself is represented in the same form as the data structures, you can very easily generate executable programs by just slapping lists together. I'd recommend going back to the Scheme version-- I initially didn't understand the cool factor of Lisp either, until I used it for a while (and found macros).
I definitely recommend you to finish the Scheme-based SICP. Plenty of stuff in the original SICP like metalinguistic abstraction is just awkward or impossible in Python.
If python didn't have with blocks, I could replicate the behavior by manually writing out a try/except/finally. I cannot write something to do that for me automatically (ignoring eval/exec). Where functions allow abstraction over a sequence of instructions, code generation allow abstraction over syntax, allowing the invention of new language features.
Try Elixir, it supports macros. Also Rust has Macros too. Although Lisp macros is different and may be more old fashion in some aspects, but it won't be hard to get the idea of code generating language, just pick one and try it.
There is no Python SICP. It pains me to see you waste your time with someone's inferior regurgitation/butchering of material written and presented by absolute geniuses that should be considered among the highest forms of art produced in the field.