UP | HOME

Introduction to Python

Overview

This document is a guide to python tailored to the MS in Robotics program at Northwestern University. It is meant to be a quick reference and a place to gather external resources rather than a full tutorial. For more information see Other Learning Resources.

Python Basics

Python REPL

  • A read-evaluate-print loop (REPL) lets you code interactively. Can run python3 or (recommended) ipython3 to enter the REPL.
  • IPython has many nice features: for example better tab completion and (with a little work) auto reloading of changed modules
  • Start your REPL!

Best Practices

  • These practices are good to think about, even when learning.
    • It is okay and even expected that you will not yet understand everything in this section, but you should be aware that practicing programming as an engineering discipline requires thinking about not just the functionality of the code but also its other properties (e.g., maintainability and reliability).
  • PEPx - Python Enhancement Proposals are official python statements about the language
    • Must Read: PEP20 to understand python's philosophy (its short).
    • Read PEP8 to learn how to "properly" format your code.
    • The Google python style guide also has some good tips.
  • Proper Documentation is important and expected for your code (we can slack a little during the hackathon but not in class or for projects).
    1. If you create a file, use a docstring to describe what the file is for
    2. When you write a class (and python is Object Oriented so you should), use a docstring to describe the class
    3. When you write a method or function, use a docstring to describe the method and parameters
    4. Docstring should be formatted for use with sphinx, which, using autodoc can be setup to automatically generate nice documentation.
      • Can use google docstring format, scipy format or native sphinx format within the docstrings themselves.
    5. Code without documentation is incomplete and time-savings from avoiding documentation prove illusory the more a project is used.
  • Testing
    • In a dynamic language like python, unit testing is especially important.
    • For many projects (e.g., research-level as opposed to safety-critical) I follow a practical philosophy when it comes to tests that I attempt to codify here:
      • Tests are your friend, bugs are the enemy.
      • If you encounter a bug, first write a test to reproduce it, then fix it.
      • If writing a test will help you think through some code (e.g., by providing example usage), write the test first.
      • If writing some code will help you think through a test, write the code first (but don't forget the test).
      • If the goal of the software involves safety, reliability, or maintainability then it also involves proper testing.
      • Always remember that tests need to be maintained alongside code. Focus testing efforts where benefits outweigh the costs.
      • Test interfaces not implementations.
      • If it is easy to write the test, do it.
      • If it is hard to test some code consider refactoring, but don't refactor just for the sake of testing.
      • Some tests are better than no tests.
      • In robotics, testing involves hardware as well as software.
    • Python has a built-in unit testing framework called unittest.
    • The third-party pytest unit testing framework is commonly used because it enables testing with less boilerplate code
  • Type Annotations
    • Python now has type annotations, allowing you to specify the types of variables
    • These types provide information to the programmer but are not enforced by the interpreter (although a separate type checker can be run)
    • I would recommend types for long-running and complex projects, but for short throw-away scripts they become less useful

Language Properties

Some basic properties of python:

  • Interpreted: reads line by line and converts source code to machine code (not entirely true, it is more optimized than this crude simplification).
  • Object oriented: everything is an object, even basic integers (object is collection of data and methods, called members):
    • use dir() to see methods of an object. What methods does the interger 1 have?
  • Strongly, but dynamically, typed:
    • Every object has a type.
    • Using the wrong type causes a runtime error.
    • Use type to see the type of an object.
  • Duck Typed - "if it quacks like a duck it's a duck".
    • If you call methods on an object, as long as the object has those methods defined, it will not be a type error.
    • Much of the flexibility in python comes from this property, which enables users to avoid needing rigid class inheritance hierarchies.

Syntax Properties

  • Significant Whitespace: tab, newlines, spaces matter.
    • As per PEP8, don't use tabs.
    • Code blocks are determined by indentation level.
    • A good text editor helps you avoid worrying about formatting too much.
  • For C and C++ folks: lines do not end in a semicolon.
  • Branching statements, function and class definitions end with a colon :.
  • Functions and variables must start with a letter or underscore and are case sensitive.
  • Class members are accessed with .. Functions are called with ().
  • Private class members start with an underscore, but can still technically be accessed.
  • Strings can use single '' or double "" quotes.
  • Python has a module system. Modules can be imported using import statements or from statements.
    • How a module is imported determines how it changes the default namespace.
    • If you import amodule you access elements in that module as amodule.item
    • If you from amodule import X you can access X directly
    • You can do import module as m to access items in module as m.item
    • Generally, you should avoid doing from module import * which brings all items in module into your namespace, but it can be useful, especially to test something in the repl quickly

Built-in Types

Some types are built in to the python interpreter (as opposed to types you define yourself).

  • int, float, long, complex, boolean (True, False).
  • Sequence Types: string, list, tuple
    • string - Use double or single quotes. "Hello" or 'hello'
    • list - A collection of objects that can be modified. Use square brackets [1, "2434", True]. Objects in a list need not be the same type.
      • Lists can be indexed with square brackets mylist[index].
      • The first element in the list is 0.
      • Indexes can count backwards from the end: the last element is index -1.
      • A sub-list can be returned using a range: mylist[2:4] retrieves elements 2 and 3 from mylist
    • tuple - a collection of objects that cannot be modified, uses parentheses (a, b). Tuples can be indexed like lists
    • dict - A hashtable that enables looking up a value based on a key. Uses curly braces. { key : value}
      • A value can be accessed with a key mydict["hello"] refers to the value associated with the "hello" key.
    • bytes - An immutable array of bytes.
    • bytearray - A mutable array of bytes.
  • High performance and advanced data types can be accessed using the collections package: import collections.
Python2 Types

Some types that were removed in Python 3 but are present in Python 2 are unicode (not needed in Python 3 because all strings are unicode), buffer, and xrange. The lack of these types is part of the major incompatibilities between python 2 and 3.

Exploring Python and Getting help

  1. Official python documentation: https://docs.python.org/3. There is also a tutorial. If you go through the tutorial, you will be pretty well on your way.
    • Even after getting help elsewhere, it is a good idea to go back to the official documentation and fully understand what you are doing.
  2. use help() to bring up information about an object or a type help(dict), help([1,2,3]).
  3. type(obj) gets the type of the object
  4. dir(obj) gets the methods associated with an object.
    • dir() gets everything defined in current namespace
    • dir(__builtins__) to see what builtins are available.
  5. To see the type of an object, use type()

Documentation in the Age of AI Chat Bots

You may be wondering: are the built-in help methods useful in the age of AI chat-bots? This question could have been similarly asked prior to these bots being viable sources of information, why use help() inside the repl when you can just google it? The answer is up to each individual, however, it can be helpful to directly receive authoritative and comprehensive information (you have narrowed down the most likely source of error to yourself). Sometimes, however, it is faster to get someone (or something) elses quick explanation, even if it may be slightly incorrect or not cover all scenarios.

Libraries and Pip

There are many libraries available for python. Many of these libraries are native python code while others are thin wrappers around a C or C++ library. Incompatibilities between versions and weird installation directories can cause a large variety of problems. The advice I give below should help you avoid many of them.

Pip

  • Python has its own package manager, called pip. On Ubuntu you call it via pip3.
  • Packages for pip are hosted on https://www.pypi.org.
  • Incompatibilities between different package versions from different sources often cause a mess.
  • Many python3 packages are already packaged for Ubuntu and are called python3-<packagename>
    • These packages are referred to as system packages
  • The current version of pip on Ubuntu prevents you from installing packages with pip unless they are installed into a virtual environment.

Virtual Environments

Virtual Environments enable you to create separate directories with different versions and combinations of python packages installed. Modern python development practices highly encourage the use of virtual environments for everything

To create a virtual environment:

  1. Run python3 -m venv path/to/my/venv (the path can be anything, but is ideally an empty or non-existent directory)
    • This command creates a virtual environment in a directory called path/to/my/venv/
    • By default packages in the virtual environment will not use your system-wide packages. Pass --system-site-packages to allow access.
  2. Activate the virtual environment using source path/to/my/venv/bin/activate
  3. When the virtual environment is active, pip will install packages to that environment.
    • These packages will not affect the rest of the system, and will not be used outside the virtual environment.
  4. To leave the virtual environment, type deactivate
  5. Pip packages that depend on external C/C++ libraries can get complicated. You will either have to follow special instructions for how to install them into the virtual environment or rely on system-wide installed packages

Python and ROS 2

  1. ROS 2 is designed around the use of system-packages, not virtual environments
    • This means that all (most? maybe there are exceptions, but I don't know of any) ROS 2 packages that are distributed by ROS (e.g., you can apt install them from ROS's package repository) depend on the system version of that package that have python dependencies
    • If your project is using ROS 2 then it is generally best to rely on system packages
  2. If you wish to distribute a ROS 2 package in binary form from the ROS 2 package server and it depends on a pip package, get the python package accepted into Ubuntu or ROS directly
  3. In your own development you can use packages installed via pip.
  4. The best way to do so (in the context of ROS) is as follows:
    1. Obtain a list of the project's python dependencies (e.g., the requirements.txt)
    2. For each dependency, check if it is available via apt (using apt-search)
    3. If it is available, install that package via apt
    4. After all available system dependencies are installed create a virtual environment and pass it the --system-site-packages flag
      • This will cause the virtual environment to use the system-installed packages
    5. Activate the virtual environment and install the package via pip
    6. Build ROS package as normal, with the virtual environment active
    7. If some of the system-packages don't work or are the wrong version, install the correct version into the virtual environment.
  5. Usually in ROS 2, a python package's source code can be placed in the src directory and it will be installed into the ROS workspace

Anaconda

Anaconda is a distribution of python primarily designed to make it easier to install on non-linux systems.

  1. You have no reason to install anaconda; you already have python on your system and are able to use pip and virtual environments.
  2. Do NOT, under ANY circumstances, install Anaconda.
    • You do not need it and it can easily destroy your ROS installation by overriding python paths and packages and introducing incompatible versions of packages.
    • Many professors tell students to install anaconda because this makes it easier to explain to a class where everyone has a different system how to setup python.
    • It does not mean that anaconda is actually needed for the class!
    • Not installing anaconda may require some extra effort on your part to install the proper python libraries: this is great practice because setting up python environments is an important skill.
  3. If you have installed anaconda and run into any python-related problem
    1. I will first tell you to uninstall anaconda (Usually this fixes the problem)
    2. If uninstalling does not work I will assume that Anaconda (or the steps taken to recover) irreparably messed up your python installation and advise you to reformat your computer.
  4. Do not install anaconda.
  5. In the past, students who have ignored this admonition have each spent hours debugging issues that are ultimately solved by uninstalling anaconda.
  6. If a project only supports installation via anaconda, that does not mean you need to use anaconda: you can install via other means with a little work
    • This extra effort is worth it, so you do not mess up your ROS installation!

Important Third-Party Libraries

Here are some commonly used libraries. I typically install these through apt since I like to have them available whenever I run python3 casually from the command line and also want the version shipped with Ubuntu to be used for maximum ROS compatibility.

  1. Numpy - For math operations
  2. Matplotlib - For plotting
  3. Scipy - extra scientific programming tools, like numerical integration. Builds on numpy
  4. pandas - useful for manipulating data tables
  5. pyserial - for using the serial port
  6. pytorch - for machine learning
  7. sympy - symbolic algebra
  8. pygame - python gaming library. Not all fun and games though, useful for doing animated graphics
  9. PyQt - used for making guis in python using the QT framework
  10. Requests - used for making http requests. Python has built-in functionality for this but many find Requests is easier
  11. sphinx - generate documentation from python packages

Exceptions to using apt

Some scientific libraries (particularly machine learning libraries) are out-of-date in Ubuntu in a way that inhibits their functionality. Using these libraries also puts you behind the curve in a fast moving field. In this case, pip and a virtual environment is often the solution.

  1. pytorch - A machine learning library from Meta. My preferred library because it has an easier to use API than tensorflow and is more widely used in academia (and catching up rapidly in industry).
  2. tensorflow - Google's machine learning library.

Warm-up Exercise

Game Description

  1. In the game of Nim, there are \(N\) rows with \(M_N\) matchsticks in row \(N\).
  2. There are two players who take turns.
  3. On each turn, the player may take any number of matchsticks from a single row.
  4. The goal of the game is to force the other player to take the last matchstick.
nim.svg
Figure 1: A Nim game with \(N = 3\), \(M_1 = 3\), \(M_2 = 4\) and \(M_3 = 5\).

Basic game

  1. Implement the game with \(N = 3\), \(M_1 = 3\), \(M_2 = 4\), and \(M_3 = 5\).
  2. The game board can be represented with ASCII characters printed to the console.
  3. After each turn, the next state of the game is displayed.
  4. Each player taking turns at the same keyboard

Additional Features

  1. Allow the user to setup the initial game board with as many rows and items in each row as desired.
  2. Implement a computer player that executes perfect play for the game.
  3. Implement a networked version, that allows players to connect to a game server and play each other.
  4. Use pygame to make a graphical version of the game.

Other Learning Resources

  1. Official python documentation
  2. Official Python Tutorial
    • If you have never done object oriented programming, you should complete this tutorial.
  3. Python Crash Course 2nd Edition by Eric Matthes (free Online access through the Northwestern Library)
  4. Official Python Howtos
  5. Python Enhancement Proposals

Author: Matthew Elwin.