Python is a great first programming language; it’s clear and easy to get up and running. More important, there are a lot of other users to share code with and ask questions.
Guido van Rossum created Python, and very early on recognized its use as a first language for computing. In 1999, van Rossum put together a widely read proposal called “Computer Programming for Everybody” that laid out a vision for an ambitious program to teach programming in elementary and secondary schools using Python. More than a decade later, it looks like it is actually happening with the coming of the Raspberry Pi.
Python is an interpreted language, which means that you can write a program or script and execute it directly rather than compiling it into machine code. Interpreted languages are a bit quicker to program with, and you get a few side benefits. For example, in Python you don’t have to explicitly tell the computer whether a variable is a number, a list, or a string; the interpreter figures out the data types when you execute the script.
The Python interpreter can be run in two ways: as an interactive shell to execute individual commands, or as a command-line program to execute standalone scripts. The integrated development environment (IDE) bundled with Python and the Raspberry Pi is called IDLE.
The best way to start learning Python is to jump right in. Although you can use any text editor to start scripting, we’ll start out using the IDE. Open up the IDLE 3 application. To run IDLE, click the desktop menu in the lower left, and choose Programming→Python (IDLE 3).
When IDLE opens you’ll see a window with the interactive shell. The triple chevron (>>>
) is the interactive prompt; when you see the prompt, it means the interpreter is waiting for your commands. At the prompt, type the following:
>>> print("Saluton Mondo!")
Hit Enter or Return. Python executes that statement and you’ll see the result in the shell window. You can use the shell as a kind of calculator to test out statements or calculations:
>>> 3+4+5
12
Think of the statements executed in the interactive shell as a program that you’re running one line at a time. You can set up variables or import modules:
>>>import math
>>>(1 + math.sqrt(5)) / 2
1.618033988749895
The import
command makes all of Python’s math functions available to your program (more about modules in “Objects and Modules”). To set up a variable, use the assignment operator (=
):
>>>import math
>>>radius = 20
>>>radius * 2 * math.pi
1256.6370614359173
If you want to clear all variables and start in a fresh state, select Shell→Restart Shell to start over. You can also use the interactive shell to get information about how to use a particular statement, module, or other Python topics with the help()
command:
help("print")
To get a listing of all of the topics available, try:
help("topics") help("keywords") help("modules")
The Python interpreter is good for testing statements or simple operations, but you will often want to run your Python script as you would a standalone application. To start a new Python program, select File→New Window, and IDLE will give you a script editing window (see Figure 4-1).
Try typing a line of code and selecting Run→Run Module. You’ll get a warning that “Source Must Be Saved OK To Save?”. Save your script in your home directory as SalutonMondo.py and you’ll see it execute in the shell.
Sometimes you may not want to use the IDLE environment. To run a script from the command line, open up the Terminal and type:
python SalutonMondo.py
That’s really all of the basic mechanics you need to know to get up and running with the environment. Next, you’ll need to start learning the language.
If you’re coming to Python from the Arduino world, you’re used to writing programs (known as sketches in Arduino, but often called scripts in Python) in a setup/loop format, where setup()
is a function run once and loop()
is a function that executes over and over. The following example shows how to achieve this in Python. Select New Window from the shell in IDLE 3 and type the following:
# Setup n = 0 # Loop while True: n = n + 1 # The % is the modulo operator if ((n % 2) == 0): print(n)
Select Run Module, and give your script a name (such as CountEvens.py). As it runs, you should see all even integers printed (press Ctrl-C to interrupt the output, because it will go on forever).
You could also implement this using a for
loop that just counts the first 100 even integers:
for n in range(0, 100): if ((n % 2) == 0): print(n)
In the preceding example, you may not notice that each level of indentation is four spaces, not a tab (but you can press Tab in IDLE, and it will dutifully insert spaces for you). Indentation has structural meaning in Python. This is one of the big stumbling blocks for beginners, or when copying and pasting code. Still, we feel that the mandatory use of whitespace makes Python a fairly readable language. See the Python Style Guidelines for tips on writing readable code.
It is important to watch your whitespace; Python is a highly structured language where the whitespace determines the structure. In the next example, everything indented one level below the loop()
function is considered part of that function. The end of a loop is determined by where the indentation moves up a level (or end of the file). This differs from languages like C that delimit blocks of code with brackets or other markers.
Use functions to put chunks of code into a code block that can be called from other places in your script. To rewrite the previous example with functions, do the following (when you go to run it, save it as CountEvens.py):
# Declare global variables n = 0 # Setup function def setup(): global n n = 100 def loop(): global n n = n + 1 if ((n % 2) == 0): print(n) # Main setup() while True: loop()
In this example, the output will be every even number from 102 on. Here’s how it works:
First, the variable n
is defined as a global variable that can be used in any block in the script.
Here, the setup()
function is defined (but not yet executed).
Similarly, here’s the definition of the loop()
function.
In the main code block, setup()
is called once, then loop()
.
The use of the global
keyword in the first line of each function is important; it tells the interpreter to use the global variable n rather than create a second (local, or private to that function) n variable usable only in the function.
This tutorial is too short to be a complete Python reference. To really learn the language, you may want to start with Learn Python the Hard Way, Think Python, or the Python Pocket Reference. The rest of this chapter will give you enough context to get up and running with the later examples and will map out the basic features and modules available.
You’ll need to understand the basic syntax of dealing with objects and modules to get through the examples in this book. Python is a clean language, with just 34 reserved keywords (see Table 4-1). These keywords are the core part of the language that let you structure and control the flow of activity in your script. Pretty much everything that isn’t a keyword can be considered an object. An object is a combination of data and behaviors that has a name. You can change an object’s data, retrieve information from it, and even manipulate other objects.
Conditionals | Loops | Built-in functions | Classes, modules, functions | Error handling |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|||
|
|
|||
|
In Python, strings, lists, functions, modules, and even numbers are objects. A Python object can be thought of as an encapsulated collection of attributes and methods. You get access to these attributes and methods using a simple dot syntax. For example, type this at the interactive shell prompt to set up a string object and call the method that tells it to capitalize itself:
>>>myString = "quux"
>>>myString.capitalize()
'Quux'
Or use reverse()
to rearrange a list in reverse order:
>>>myList = ['a', 'man', 'a', 'plan', 'a', 'canal']
>>>myList.reverse()
>>>print(myList)
['canal', 'a', 'plan', 'a', 'man', 'a']
capitalize()
and reverse()
.Some of the standard library modules are not built-in, and you need to explicitly say you’re going to use them with the import
command. To use the time
module from the standard library to gain access to helpful functions for dealing with timing and timestamps, use:
import time
You may also see import as
used to rename the module in your program:
import time as myTime
Or from import
used to load select functions from a module:
from time import clock
Here’s a short example of a Python script using the time
and datetime
modules from the standard library to print the current time once every second:
from datetime import datetime from time import sleep while True: now = str(datetime.now()) print(now) sleep(1)
The sleep
function stops the execution of the program for one second. One thing you will notice after running this code is that the time will drift a bit each time.
That’s for two reasons:
The code doesn’t take into account the amount of time it takes to calculate the current time.
Other processes are sharing the CPU and may take cycles away from your program’s execution. This is an important thing to remember: when programming on the Raspberry Pi, you are not executing in a real-time environment.
If you’re using the sleep()
function, you’ll find that it is accurate to more than 5ms on the Pi.
Next, let’s modify the example to open a text file and periodically log some data to it. Everything is a string when handling text files. Use the str()
function to convert numbers to strings (and int()
to change back to an integer):
from datetime import datetime from time import sleep import random log = open("log.txt", "w") for i in range(5): now = str(datetime.now()) # Generate some random data in the range 0-1024 data = random.randint(0, 1024) log.write(now + " " + str(data) + "\n") print(".") sleep(.9) log.flush() log.close()
In a real data-logging application, you’ll want to make sure you’ve got the correct date and time set up on your Raspberry Pi, as described in “Setting the Date and Time”.
Here’s another example (ReadFile.py) that reads in a filename as an argument from the command line (run it from the shell with python3 ReadFile.py
filename
. The program opens the file, reads each line as a string, and prints it. Note that print()
acts like println()
does in other languages; it adds a newline to the string that is printed. The end
argument to print()
suppresses the newline:
# Open and read a file from command-line argument import sys if (len(sys.argv) != 2): print("Usage: python ReadFile.py filename") sys.exit() scriptname = sys.argv[0] filename = sys.argv[1] file = open(filename, "r") lines = file.readlines() file.close() for line in lines: print(line, end = '')
One of the reasons Python is so popular is that there are a great number of user-contributed modules that build on the standard library. The Python Package Index (PyPI) is the definitive list of packages (or modules); some of the more popular modules that are particularly useful on the Raspberry Pi are shown in Table 4-2. You’ll be using some of these modules later on, especially the GPIO module to access the general inputs and outputs of the Raspberry Pi.
Module | Description | URL | Package name |
---|---|---|---|
RPi.GPIO |
Access to GPIO pins |
python-rpi.gpio |
|
GPIOzero |
Simplified access to GPIO pins |
python-gpio-zero |
|
Pygame |
Gaming framework |
python-pygame |
|
SimpleCV |
Easy API for Computer Vision |
No package |
|
SciPy |
Scientific computing |
python-scipy |
|
NumPy |
The numerical underpinings of Scipy |
python-numpy |
|
Flask |
Microframework for web development |
python-flask |
|
Feedparser |
Atom and RSS feed parser |
No package |
|
Requests |
“HTTP for Humans” |
python-requests |
|
PIL |
Image processing |
python-imaging |
|
wxPython |
GUI framework |
python-wxgtk2.8 |
|
pySerial |
Access to serial port |
python-serial |
|
PyUSB |
FTDI-USB interface |
No package |
To use one of these, you’ll need to download the code, configure the package, and install it. The NumPy
module, for example, can be installed as follows:
sudo apt-get install python-numpy
If a package has been bundled by its creator using the standard approach to bundling modules (with Python’s distutils tool), all you need to do is download the package, uncompress it, and type:
python setup.py install
In later chapters, you’ll use application-specific modules extensively, but here’s one example that shows how powerful some modules can be. The Feedparser module is a universal parser that lets you grab RSS or Atom feeds and easily access the content. Because most streams of information on the Web have RSS or Atom output, Feedparser is one of several ways to get your Raspberry Pi hooked into the Internet of Things.
First, install the Feedparser module using Pip (see “Easy Module Installs with Pip”):
sudo pip install feedparser
To use it, simply give the parse function the URL of an RSS feed. Feedparser will fetch the XML of the feed and parse it, and turn it into a special list data structure called a dictionary. A Python dictionary is a list of key/value pairs, sometimes called a hash or associative array. The parsed feed is a dictionary, and the parsed items in the feed are also a dictionary, as shown in this example, which grabs the current weather in Providence, RI, from http://weather.gov:
import feedparser feed_url = "http://w1.weather.gov/xml/current_obs/KPVD.rss" feed = feedparser.parse(feed_url) RSSitems = feed["items"] for item in RSSitems: weather = item["title"] print weather
Python makes it fairly easy to trigger other programs on your Pi with the sys.subprocess
module. Try the following:
from datetime import datetime from time import sleep import subprocess for count in range(0, 60): filename = str(datetime.now()) + ".jpg" subprocess.call(["fswebcam", filename]) sleep(60)
This is a simple time-lapse script that will snap a photo from a webcam once a minute for an hour. Cameras are covered in greater detail in Chapter 9, but this program should work with a USB camera connected and the fswebcam
program installed; run this command first to install it:
sudo apt-get install fswebcam
The subprocess.call
function takes a list of strings, concatenates them together (with spaces between), and attempts to execute the program specified. If it is a valid program, the Raspberry Pi will spawn a separate process for it, which will run alongside the Python script. The command in the preceding example is the same as if you typed the following at a terminal prompt:
fswebcam 20160812.jpg
To add more parameters to the program invocation, just add strings to the list in the subprocess.call
function:
subprocess.call(["fswebcam", "-r", "1280x720", filename])
This will send the fswebcam
program a parameter to change the resolution of the snapped image.
Inevitably, you’ll run into trouble with your code, and you’ll need to track down and squash a bug. The IDLE interactive mode can be your friend; the Debug menu provides several tools that will help you understand how your code is actually executing. You also have the option of seeing all your variables and stepping through the execution line by line.
Syntax errors are the easiest to deal with; usually this is just a typo or a misunderstood aspect of the language. Semantic errors—where the program is well formed but doesn’t perform as expected—can be harder to figure out. That’s where the debugger can really help unwind a tricky bug. Effective debugging takes years to learn, but here is a quick cheat sheet of things to check when programming the Pi in Python:
Use print()
to show when the program gets to a particular point.
Use print()
to show the values of variables as the program executes.
Double-check whitespace to make sure blocks are defined the way you think they are.
When debugging syntax errors, remember that the actual error may have been introduced well before the interpreter reports it.
Double-check all of your global and local variables.
Check for matching parentheses.
Make sure the order of operations is correct in calculations; insert parentheses if you’re not sure. For example, 3 + 4 * 2
and (3 + 4) * 2
yield different results.
After you’re comfortable and experienced with Python, you may want to look at the code
and logging
modules for more debugging tools.
There is a lot more to Python, and here are some resources that you’ll find useful:
This is a clear and fairly concise approach to programming (that happens to use Python).
Because sometimes flipping through a book is better than clicking through a dozen Stack Overflow posts.
That said, Stack Overflow is an excellent source of collective knowledge. It works particularly well if you’re searching for a specific solution or error message; chances are someone else has had the same problem and posted here.
A great book and online resource; at the very least, read the introduction “The Hard Way Is Easier.”
Again, more of a general programming book that happens to use Python (and written for younger readers).