I haven’t used a dynamic language for coding nearly as much as strongly-typed, compiled languages so approaching Python was a little nervous-making for me. It’s not every day you look into the abyss of your own technical inadequacies and find a way to keep going.
Here’s how embarrassing it got for me: I knew enough to clone the code to my computer and to copy the example code into a .py file, but beyond that it felt like I was doing the same thing I always do when learning a new language: trying to guess at the basics of using the language that everyone who’s writing about it already knows and has long since forgotten, they’re so obvious. Obvious to everyone but the neophyte.
Second, is that I don’t respond well to the canonical means of learning a language (at least according to all the “Learn [language_x] from scratch” books I’ve picked up over the years), which is
- Chapter 1: History, Philosophy and Holy Wars of the Language
- Chapter 2: Installing The Author’s Favourite IDE
- Chapter 3: Everything You Don’t Have a Use For in Data Types
- Chapter 4: Advanced Usage of Variables, Consts and Polymorphism
- Chapter 5: Hello World
- Chapter 6: Why Hello World Is a Terrible Lesson
- Chapter 7: Author’s Favourite Language Tricks
I tend to learn best by attacking a specific, relevant problem hands-on – having a real problem I felt motivated to attack is how these projects came to be (EFSCertUpdater, CacheMyWork). So for now, despite a near-complete lack of context or mentors, I decided to dive into the code and start monkeying with it.
Riches of Embarrassment
I quickly found a number of “learning opportunities” – I didn’t know how to:
- Run the example script (hint: install the python package for your OS, make sure the python binary is in your current shell’s path, and don’t use the Windows Git Bash shell as there’s some weird bug currently at work)
- Install the dependencies (hint: run “pip install xxxx”, where “xxxx” is whatever shows up at the end of an error message like this:
C:\Users\Mike\code\marvelous>python example.py Traceback (most recent call last): File "example.py", line 5, in <module> from config import public_key, private_key ImportError: No module named config
In this example, I ran “pip install config” to resolve this error.
- Set the public & private keys (hint: there was some mention of setting environment variables, but it turns out that for this example script I had to paste them into a file named “config” – no, for python the file needs to be named “config.py even though it’s text not a script you would run on its own – and make sure the config.py file is stored in the same folder as the script you’re running. Its contents should look similar to these (no, these aren’t really my keys):
public_key = 81c4290c6c8bcf234abd85970837c97 private_key = c11d3f61b57a60997234abdbaf65598e5b96
Nope, don’t forget – when you declare a variable in most languages, and the variable is not a numeric value, you have to wrap the variable’s value in some type of quotation marks. [Y’see, this is one of the things that bugs me about languages that don’t enforce strong typing – without it, it’s easy for casual users to forget how strings have to be handled]:
public_key = '81c4290c6c8bcf234abd85970837c97' private_key = 'c11d3f61b57a60997234abdbaf65598e5b96'
- Properly call into other Classes in your code – I started to notice in Robert’s Marvelous wrapper that his Python code would do things like this – the comic.py file defined
…and the calling code would state
import comic … schema = comic.ComicSchema()
This was initially confusing to me, because I’m used to compiled languages like C# where you import the defined name of the Class, not the filename container in which the class is defined. If this were C# code, the calling code would probably look more like this:
using ComicSchema; … _schema Schema = ComicSchema();
(Yes, I’m sure I’ve borked the C# syntax somehow, but for sake of this sad explanation, I hope you get the idea where my brain started out.)
I’m inferring that for a scripted/dynamic language like Python, the Python interpreter doesn’t have any preconceived notion of where to find the Classes – it has to be instructed to look at specific files first (import comic, which I’m guessing implies import comic.py), then further to inspect a specified file for the Class of interest (schema = comic.ComicSchema(), where comic. indicates the file to inspect for the ComicSchema() class).
So far, I’m feeling (a) stupid that I have to admit these were not things with which I sprang from the womb, (b) grateful Python’s not *more* punishing, (c) smart-ish that fundamental debugging is something I’ve still retained and (d) good that I can pass along these lessons to other folks like me.