Back to the drawing board…

Undaunted by my ignoble initial defeat at the hands of the Silver Mystery Table, I decided to do something difficult: admit that perhaps I bit off more than I can chew, and go back to some basic Tkinter practice, including improving my understanding of Python classes. I know just enough about the concept of a class to appreciate how powerful it is, but not quite enough to pull off something useful.

Inspired by this lesson at TkDocs, I decided to have some fun by writing an application that makes people cool!  Silly, yes, but I found this is how I learn best..study basic concepts, see an example, then try it out on an idea of my own.

Since I like being surrounded by cool people, and frequently find many in need of coolness, I want to make my app very easy to use. It will prompt the user for the name of a person to be made cool, make them cool, and display a congratulatory message. Since I will probably want to use this function frequently, I’m going to put it in a module I will name “cool_tools.”

Of course, since I already know many cool people, I wouldn’t want to accidentally have my coolness function used on one of them. Not only would attempting to apply coolness to someone who is already cool insult them, it would cause the app to crash in an embarrassing way. Therefore I will need to include some code to prevent this grim scenario.

Here it is:

def coolness(name):
    """ This function makes people cool.  It will return an
            error if you attempt to use it on someone who is
            already cool."""
    # List of people who are already cool. This is a tuple, meaning
    # these individuals are unchangeably cool.
    cool_people = ("tony",
                   "kevin",
                   "bryan",
                   "matt",
                   "victor",
                   "chris",
                   "ricardo")
    for cool_person in cool_people:
        # Loops through the list of cool people, in case
        # the user inadvertently entered the name of someone
        # who is already cool.
        if cool_person == name.lower():
            result = "ERROR! Invalid usage. {} is already cool.".format(name)
            break
        else:
            result = "{} is now a cool person! CONGRATULATIONS, {}!"\
                     .format(name,name)
    return result

So, let’s test it, shall we? First, I run the module, which loads and leaves me at a Python command prompt. (I use IDLE for my coding). Then, I try it on an uncool person, and then a cool person. Result:

>>> print coolness(“Rob”)
Rob is now a cool person! CONGRATULATIONS, Rob!
>>> print coolness(“Tony”)
ERROR! Invalid usage. Tony is already cool.
>>>

It works! So, I save this function in a module called “cool_tools.py”. This means it can be imported whenever needed, and act just like a for real, serious Python tool created by a pro! It even has a “help” option (a/k/a a “docstring” — the double-quoted comment at the beginning). Here how that works:

>>> from cool_tools import coolness
>>> help(coolness)
Help on function coolness in module cool_tools:

coolness(name)
This function makes people cool. It will return an
error if you attempt to use it on someone who is
already cool.
>>>

So, now I have my very own Python function. But it’s just that — a function. It must be called from a programming environment such as IDLE, or summoned with a “python” statement from the dark, scary terminal window. It can’t rightly be called an application — yet.

What I really want is GUI application that uses this function, and looks as cool as it is! Following the example of the above TkDocs lesson, I sketch out how I’d like my app to look:

coolness_sketch

Very simple: an entry box for the name of the person to be made cool, a button to activate the coolness, and a text box below to display the result. So, without further ado, here is Apply Coolness 1.0:

# Apply Coolness 1.0
# Import my cool function first!
from cool_tools import coolness
from Tkinter import *
import ttk

# Create the root window
root = Tk()
root.title("Apply Coolness")

# Create the frame to hold the boxes & button
mainframe = ttk.Frame(root)

# Set the variable for the name entered by the user
name = StringVar()

# Label that tells the user what to do.
lblPrompt = ttk.Label(text="Enter the name of the person \
                        to be made cool:")
lblPrompt.pack()

# Box in which user enters a person's name.
txtEntry = ttk.Entry(mainframe,textvariable=name)
txtEntry.pack()

# The button that activates the coolness function.
btnCool = ttk.Button(mainframe,text="Make Cool",command=coolness(txtEntry.get()))
btnCool.pack()

# Box that displays the result of the procedure.
txtResult = Text(mainframe)
txtResult.pack()

# Set the focus to the entry box so the user won't have to
# click on it first.
txtEntry.focus()

root.mainloop()

…and here’s the result…

coolness_apply coolness10

Whoops..definitely not cool! How can it be fixed? Stay tuned!

The Quest for the Silver Mystery Table

As I have shared previously, I have worked for many years with Microsoft Access, using it both at home and at work for tracking just about everything in tables linked together in queries and forms. At home I was able to put together a (sort of) application for tracking our finances and inventory. The core of this app is a form that displays transactions and includes text and combo boxes for entering criteria for sorting, filtering and totaling, like this:

MS Access Transactions

I can view transactions by bank account, expense category, month, year, and so on. I can also enter transactions using this same form. Such functionality is a no-brainer in Microsoft Access. Behind all the boxes are string variables that are assembled together to create a SQL statement that gets me what I want to see from the data. Sorting and filtering lists of stuff like is 90% of what do in Access both at home and at work.

My primary goal in Python coding is to reproduce something like the above, using Python code, a GUI tool such as Tkinter and a SQLite database. If I could discover the secret of doing this, the possibilities for data-centric app building would become endless for me. To use a truly Pythonic analogy, this is my own, personal Holy Grail of coding. I only hope my quest meets with better success than poor King Arthur, Sir Robin and the gang

So off I went into Google-land, almost hearing the cloppety-clop of those coconuts following close behind me, and after many dead ends, false starts and Frenchmen farting in my general direction, I beheld this:
The Silver Mystery Table

Impressive!

But..how do I get it to work?

First thing I noticed: It appears to require an add-on called “pmw,” which I later found out stands for Python Mega Widgets. Sounds like an appropriately awesome name for an appropriately awesome add on, yes?

(Attention gamers: believe it or not, as I was writing this I accidentally typed “pwn” instead of “pmw!” As in, “I hope I don’t get pwnd by pmw!”)

Pmw seemed to install easily with the good old command line: python setup.py install. This time I didn’t have to summon ez_install or pip. I’m starting to think of those two as my own personal goons, ready to beat up on uncooperative toolkits who refuse to install when I ask them politely with setup.py. “Oh, so you don’t want to install, eh? We have ways of MAKING you install….”

I have learned that whenever I install a new toolkit like this, I can immediately find out if it installed correctly, right from a Python command prompt, like so:

>>> import Pmw
>>>

Success! Ah, the delightful silence of a “>>>” prompt, without lines of angry red text! Now, to copy, paste, and run. Oops..no go…got an error: ‘Table’ is not defined.” Well, obviously something is missing here, obviously. Better Google the exact name of the table thingy from the above link: “PmwContribD.” OK, now I see the ‘Table’ is part of another set of widgets called “PmwContribD”, that’s based on the set of widgets (“pmw”) that I just installed. No problem. Found it: http://ostatic.com/pmwcontribd. Thankfully, another hassle-free install. Next, I need to make sure I include the correct “import” statements in my code. According to the PmwContribD documentation for the ‘Table’ widget, they should be these. So I add these statements, and past in the code from the first link above:

from Tkinter import *
import Canvas
from CanvasGroup import CanvasGroup
import Pmw
from ShadowBox import ShadowBox
import UserList
import math
import string

self.table = Table(self.interior(), cellpadding=pad, xfreeze=1)
self.table.addcolumn( RowLabelColumn(
    title='',
    datasource=TestDataSource(),
    width=50,
    rowheight=rowheight,
    cellalignment='se',
    cellpadding=pad,
    ))
for i in range(10):
    self.table.addcolumn( Column(
        title='Col %d' % i,
        datasource=TestDataSource(base=10**i),
        #width=50 + (10 * i),
        width=0,
        rowheight=rowheight,
        cellalignment='se',
        cellpadding=pad,
        ) )
    self.table.pack(fill=Tkinter.BOTH, expand=Tkinter.YES)

So I ran it and…still getting the ‘Table’ is not defined’ error. I am now officially stuck. In looking over the code again, I suspect the problem is in the “self” statements. As I recall what I learned about classes, now that I think of it, shouldn’t there be a “class” definition before a “self?” Such as “class MyTable, or something like that? Perhaps a Python professional is out there laughing his head off at this. Nevertheless, for me, this object remains, for the time being, a mystery. So from know on I will refer to it as “The Silver Mystery Table.” Yes, I know it’s actually grayish, but silver sounds a lot cooler, like a precious, elusive treasure. Or a sword, that has cut me. But that’s OK, because I will be back. I will hone my Tkinter skills and live to fight another day!

Besides, it’s only a flesh wound.

A Snake, a Rodent and an Epiphany

A month or so ago I saw this RSS reader project at Mouse vs. Python. It was the first GUI-based Python tutorial program I ran across that had a real-world (though simple) use. I guess I’m still fascinated by actually being able to program and code a graphical interface. Yes, I’m used to Microsoft Access and VBA, but that’s still a graphical piece of software being used to build graphical objects. With Python, I can sit in front of a dark, boring command-prompt window, enter some monospaced, arcane spells in Tkinter, wxPython, or what have you, and conjure up colorful windows and widgets like a sorcerer. I’ve been eager to partake of this magic since cranking out my first post-Code Academy project (a.k.a., the Python equivalent of “See Jack Run”, literally), and here was a chance to see a “real” Python based GUI app in action, and study and tinker with its code. Therefore, once I saw this, I couldn’t wait to get in front of my laptop and take it for a spin.

Little did I know a coding epiphany was on the way. Actually, two.

As can be seen from Mike’s code, this app requires a add-on toolkit called “feedparser.” I had a devilish time getting that thing to function. It seemed to install OK, using “easy install”, yet it stumbled over the “import” statement, giving me an error along the lines of “line 154 – no module named request.” I don’t remember it exactly, and since I didn’t know then I’d be writing about the experience, didn’t save the exact error message.

Regardless, like a good coding newbie, I didn’t panic and cry for help…I Googled it first. Well, as I recall, the only hit that even seemed to approximate my situation was a Python forum in Chinese. Dauntless, I ran it through Google Translate and did my best to decipher the somewhat broken English it spat out. Still no help. I started to get frustrated. All I wanted to do was try this cool RSS app, and here I was, spending most of a day on an uncooperative dependency that was tripping up the code on its very first line. “This isn’t what I planned!”, I growled to myself.

Exactly. Because that, folks, is what I realized is a major part of a coder’s life: confronting and solving unexpected problems, and learning (even against my will) in the process. Sometimes my biggest coding project will be something unexpected that interrupts the project I’m really excited about, and I will have to digress.

I realized that if I can’t handle such digressions, then I won’t be able to handle being a coder.

And guess what? I handled it.

You see, I recalled that there was another popular method for installing Python packages: something called “pip”, which one of my earlier tutorials had told me I needed, and therefore, I had installed it.  So, just for kicks, I went to my command prompt and typed: “pip install feedparser.”

That did it! Now the code was off and running, and a great big RSS reader GUI window materialized before my eyes! All I had to do was click the “Get Feed button…”

Crash. Another error. Now the code told me it needed an object called “RSS”, which was not defined. So, I searched and searched through the code, and couldn’t find it. I tried lowercasing “RSS” in the offending statement, and other random, clueless thrashing about, to no avail. Alas, I was beaten. So I broke down. I asked Mike for help.

He was kind and patient, suggesting I re-check the code I’d copied and pasted from his blog. And there, lo and behold, was an entire chunk…the ‘RSS’ class definition..that I had neglected to copy and paste! I’d probably let my cursor get ahead of my scroll wheel, or something like that. I pasted it in, and..eureka! There was the RSS article list and summary on my left, and a glorious in-app web browser in the big window on the right! I did it! I’m magic! (or, at least, I was able to get Mike’s magic to obey a wizardly newcomer).

So, here was the second epiphany: sometimes, after giving a challenge my best effort, I need to know when to humble myself and get help. Thankfully, in the Python world, there are plenty who are ready to do so.

Python Web development. It’s killer.

Before I start today’s post, I would like to give a huge shout-out to my good friend Dana at Accularian, who generously and unexpectedly donated hosting space, enabling My Python Adventure to move to its own home on the Web!

In my early days of Python (read: less than 6 months ago), I seem to recall reading that web-based applications are the wave of the future. I discovered web2py and learned that a web app can live on my local computer as well as online and reasoned, why bother learning how to write desktop based apps at all, if a web based app can be both desktop and online? I decided to jump right in to web development, fresh out of Code Academy, and web2py turned out to be simple to install and easy to set up (Django was another matter entirely, but that’s a topic for another post.) As I rummaged around the internet looking for a web2py tutorial, I found Killer Web Development.

An amusing aside: at some point I mis-typed the URL and ended up with a “Page Not Found” error, with a sidebar of other suggestions along the lines of “Murderer Web Development”, “Assassin Web Development”, etc.  I hope the internet’s slang-recognition algorithms improve before I get in trouble with Homeland Security.

The best thing about this tutorial is it not only gives a thorough introduction to basic concepts of web development (such as model-view-controller), it also introduces essentials of coding in general, such as version control, using and sharing repositories and test-driven development. I was clueless about all of these before. The author is not a native speaker of English so his grammar is hard to follow at times, but on the other hand, he’s doing way more than I could dream of. I doubt I could come up with an intelligible toilet flushing tutorial in German, even with Google Translate, never mind a highly technical topic like Herr Laspe dared to tackle in a foreign language. His enthusiasm for his subject matter shines through, and is contagious. I came away with the sense that I’d learned, hands-on, all the essential steps of professional programming — not just the particulars of a specific language or tool. This was extraordinarily valuable. Now so much of what I hear from the coding community, phrases like “repository”, “testing framework”, etc. is less and less Greek to me.

I also learned from this site that “web development” Python is almost like a different language from “Code Academy” Python. In studying the web2py code I’d created in the tutorial, it seemed to resemble very little of what I thought I had learned. I therefore decided to do something that is difficult for me: admit that I perhaps bit off more than I can chew, back up and start again from a simpler foundation. So now, off to desktop GUI building.  Hello, Tkinter!

How the adventure began..

A regret that has haunted my adult life off and on is not majoring in computer science when I was a college student ( a longer time ago than I care to admit).  I took my first computer programming class when I was in middle school and loved it, but as a college kid, the word “hard” followed by “work” was not in my vocabulary.  If an endeavor did not come instantly and naturally easy to me, and stay easy, then I’d conclude it was not for me. In other words, I was lazy. A computer science degree required calculus, a class which I tried for two weeks in my sophomore year, then promptly dropped because it scared me so much.  And that was the end of any formal pursuit of a technical career. Nevertheless, as the years went by and I found myself drawn to using various available software tools to manage data at my workplaces, I started to feel like there was a frustrated techie stuffed inside the average Joe Office Guy I’d become.

Sometime last summer (2013), I ran across some articles about the explosion in the need for programmers, especially for web development, and a corresponding rise in the availability of free online resources to learn programming.  Suddenly that old youthful enthusiasm for telling computers what to do sprang back up.  Through these articles, I found Code Academy and promptly jumped right in to their Web Fundamentals and Python tracks.  It’s great for beginners because the lessons, writing the code and running it are all self-contained on the site.  The user doesn’t even need to install Python on their PC.  It’s also a good way to figure out if coding is really for you, without too much sweat.  If you come away from a Codeacademy course excited and wanting more, as I did, then great!  If you come away “meh”, then at least you haven’t wasted too much time.

Thanks to Code Academy, I was able to develop my very first app: a little program that calculates a runner’s pace and average miles per hour, and stores a run history in a database.   Of course it will never compete with Runtastic (the app I use on my mobile phone to track my running), but at least it allows me to show off the fact that I learned something.