[REP Index] [REP Source]

REP:8
Title:Style Guide for Python Code
Author:Ken Conley <kwc at willowgarage.com>
Status:Active
Type:Process
Content-Type:text/x-rst
Created:18-Sep-2010
Post-History:18-Sep-2010

Abstract

This document gives coding conventions for the Python code comprising the standard library in the main ROS distribution.

Coding Style

Please follow Python's PEP 8 [1] for guidelines on formatting, naming, etc...

The Loader

roslib is the only ROS Python package you can automatically assume to be importable other than your local files. If your Python package has dependencies, you must include the following header at the top:

import roslib
roslib.load_manifest('your_package_name')

roslib.load_manifest looks at your manifest.xml and places your dependencies on your Python path. DO NOT use multiple load_manifest calls. If you need multiple calls, it's probably because you're missing the correct dependencies in your manifest.

Package/Module Names (__init__.py files)

All python code must be placed within a module namespace. ROS exports your Python source directory to be on the path of any of your dependencies, so it is important not to accidentally clobber someone else's import. We strongly recommend that this module name be the same as your ROS package name.

There are two recommended code layouts:

Small modules with no msg/srvs:

packagename
 |- nodes/
    |- ROS node executable files
 |- src/
    |- packagename.py
 |- scripts/
    |- non-exported python files

Module with msgs/srvs:

packagename
 |- nodes/
    |- ROS node executable files
 |- src/
    |- packagename/
      |- __init__.py
      |- yourfiles.py
 |- scripts/
    |- non-exported python files

We distinguish between "nodes" and "scripts" for clarity to users. Nodes are executable Python files that conform to the ROS node API. Scripts are executable Python files that do not conform to the ROS node API.

If you don't know what an __init__.py file is, we recommend that you read What is init py used for??

The more complicated layout for msg/srv files is required as the Python msg/srv generators will need to generate files into your package's namespace.

In the rare case that you can't place your source code in src/ (e.g. thirdparty code), you can override the Python export path of your package by editing your manifest.

Node Files

In ROS, the name of a node type is the same as its executable name. Typically, for python files, this means including #!/usr/bin/env python at the top of your main code file.

If your node is simple, this file may contain the entire code for it. Otherwise, the node file will likely do an import packagename and invoke code there.

NOTE: we strive to keep ROS-specific code separate from reusable, generic code. The separation of 'node files' and files you place in src/packagename helps encourage this.

Python Features and Version

The current target platform is Python 2.5 [2], though we wish to make code that is easily transitioned to Python 2.6, 2.7, and, more importantly, Python 3000 [3].

This means:

  • Use new-style classes
  • No reduce(). sum() works in most cases and for loops are often as fast or faster
  • Try to avoid map() or filter() as they are on Guido's hit list. Use list comprehensions.
  • Use raise Exception("msg") instead of raise Exception, msg
  • No backticks as a shortcut for repr
  • No <>, use !=
  • Use from __future__ import division so that you're using true division, not floor division [4]
  • Use subprocess instead of popen2, os.popen
  • Avoid dict.has_key(), use key in dict instead.
  • Try to avoid using the results of zip(), range(), map(), or filter() as a list as these will return iterators in the future

All the above are on this list either because:

  • They are not compatible with Python 2.5
  • They will potentially be eliminated in Python 3000.

Also, be careful not to introduce Python 2.6 features, such as Exception as ex.

References

[1]PEP 8, Style Guide for Python Code, van Rossum http://www.python.org/dev/peps/pep-0008/
[2]REP 3, Target Platforms, Foote, Conley http://www.ros.org/reps/rep-0003.html
[3]PEP 3100, Miscellaneous Python 3.0 Plans, Cannon http://www.python.org/dev/peps/pep-3100
[4]PEP 238, Changing the Division Operator, Zadka http://www.python.org/dev/peps/pep-0238