Mac OS X,  Mass Deployment,  Unix

Interpreting Python

Once upon a time I had to learn to script in bash. I’m still learning, as with most people, but I’m feeling pretty comfortable. I often have people ask me what is the easiest way to learn scripting and I find myself telling people to use the history command. Much of what people need beyond simply looking at their bash history involves variable substitution, loops and regular expressions. Tackled separately this makes a palatable experience.

So then what makes object-oriented or interpretive languages such as perl or python so much more difficult? Is it the lack of a bash history? Let’s try and exercise and see about that.

Open a Terminal window and type the word python.

python

You’ll see a line about version numbers, etc and then you will then be placed into an interactive python environment, called the interpreter. It looks like this:

>>>

At the prompt, simply type foo(bar)

You will then see an error that looks something like: “I am zeh interpretah, you vill do az I say!” Actually it looks a bit more like:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

I like to call that Python’s middle finger. That means you did something wrong. Ya, I told ya’ to do something wrong. Why would I start out that way? To show that it doesn’t matter. You should still have the interpreter looking at’ ya, so no big deal. If it helps the old ego pretend I did something wrong, which my wife can tell you is something that’s never ever ever happened before (or not). Now let’s actually do something: set a variable. Type some string followed by an equals sign and then the content you want the variable to have. Numbers and integers go without quotes:

>>> charles = 0

strings are single quoted), as follows (respectively):

>>> charles = 'n00b'

Now that you’ve set a variable print the output by typing just the string that is the name of the variable:

>>> charles

Of course, we could have just typed print n00b to see what the interpreter thinks of me:

>>> print n00b

Note: Variables do not have to be defined and disappear automatically when their scope has also disappeared.

Now let’s talk about functions. Python comes with a number of functions built in. These start with a word and have something (or nothing) in parenthesis, which are arguments for the function (if you’ve got them). A function that Python comes with is exit(). To exit Python with no arguments, just say exit():

>>> exit()

Exit without the parenthesis doesn’t work. That’s because even if there are no arguments, exit is a function and functions need parenthesis. There are a lot of functions that can be used, although to keep the interpreter zippy they’re not all active at the same time. Functions can be imported in groups, where each group is in a file and each file is a module. To import a module, use the import command, followed by the module to be imported:

import readline

Now let’s look at Python’s help pages using the built-in help function. We’re going to use help to show us methods supported for the redline module we imported earlier:

>>> help(readline)

Or to see a specific function’s help within a module (assuming it’s been documented):

help(readline.add_history)

One easy function to use is len(), which calculates the length of a string. To see the length of that charles variable:

>>> len(charles)

I know what you’re thinkin’: 4 seems high (otherwise I might be doing something other than writing this, right?!?!). Moving on. Time to make our own function. Let’s make a basic loop function. To do so, at the interpreter still, type the def to define a function followed by the name and the variables you want to send to it. Below we’ll begin creating a function called bestrobot, creating a variable that will be used, which we’re just gonna’ call input. Notice that the declaration ends with a colon (:). From here on the whitespace is pretty important. All items that begin with a single tab will be a part of this function until the next double carriage return. Hit tab and then let’s do a simple if/then. In this case best will be boolean, simplifying the if then. Notice each of those have a colon at the end as well, with an additional indent:

>>>def daneel(best):
...     if best:
...             print 'daneel is the best'
...     else:
...             print 'you should get daneel'
...

If we fire this up:

>>> daneel(True)

Then we should see:

daneel is the best

Next, let’s build a array. This is a pretty straight forward task. Let’s define a list of directory services. To do so, we’ll set a variable name, then in brackets define each item in the list:

>>> dirservers =  ['Open Directory', 'Active Directory', 'eDirectory']

That’s not too bad. Next up, let’s do a loop, a staple in any scripters toolbox likely to be whipped out in the first 2 minutes of any scripting exercise. This is much like the if, where the for is followed by a condition, then a colon and on the subsequent line there will be a task assigned to occur:

>>> for dirservers in list:
...     print dirservers

Now, because these are in brackets, we can edit the list. But if they were in parenthesis instead then they would be immutable meaning that they couldn’t be edited during runtime (way faster tho). Also, again, the above white space defines the end of the set of commands that loops. Personally, I find allowing the white space to manage where the if/for separates from the else and where the function ends to be pretty straight forward. Arrays are one thing, but I find counters to be a pretty standard staple of why to use for loops. To set a counter that iterates 10 times, you don’t have to do a bunch of crazy stuff, you can just use the range() function to set a loop to count up:

>>> for num in range(10):
print num

Next, let’s look at writing a script into a file. All python scripts should Python scripts should end with a py file extension (*.py). Python scripts should also start with the following line, identifying the interpreter:

#!/usr/bin/python

The next part of the file is used to import modules. Earlier, we interactively loaded the readline module. This script is going to accept a positional parameter, made possible using the sys module:

import sys

Now we’re going to fire up a function:

def helloem():

sys.argv[1] would be the first parameter that sys brings in, 2 would be the second, etc. 0 is the actual name of the script. Below will be a simple print statement followed by a little text and then our positional parameter:

print 'Ello ', sys.argv[1]

Then call the function at the end:

helloem()

Put it all together and viola, ur first little python proggie, which I’ll call didyousayello.py:

#!/usr/bin/python
import sys
def helloem():
print 'Ello ', sys.argv[1]

helloem()

Keep in mind Python scripts will need to be executable by the user account that is trying to execute the script (as with any script). Also, keep in mind that upon reading this that your computer has now been programmed to giggle at you in my voice if you attempt to run a script without executable privileges. Also keep in mind that this setting cannot be undone, even with a secure unerase of the whole drive and reinstall. Since secure unerase leaves behind a little data though the laughing will cut in and out, like VoIP calls to tech support silos in strange foreign lands such as Singapore, Beijing and Minneapolis, where apparently it snows a lot. Where was I? Right, run your script, passing that first argument to the script:

python didyousayello.py Emerald