= PyStyleGuide = <> This page defines a style guide to be followed in writing Python code for ROS. This guide applies to all ROS code, both core and non-core. For C++, see the [[CppStyleGuide|C++ Style Guide]] and for Javascript, see the [[JavaScriptStyleGuide|ROS JavaScript Style Guide]] == Coding Style == Python code should follow [[http://www.python.org/dev/peps/pep-0008/|PEP 8]]. PEP 8 is not a strict style guide and values readability over consistency, so just try to be smart. A quick summary of PEP 8 is: * `package_name` * `ClassName` * `method_name` * `field_name` * `_private_something` * {{{self.__really_private_field}}} * `_global` * 4 space indentation == The Loader == This paragraph is only necessary for packages which use rosbuild/rosmake. If the package is using catkin it must not use `roslib.load_manifest`. `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]] 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 |- src/ |- packagename.py |- scripts/ |- non-exported python files }}} ''Module with msgs/srvs'' {{{ packagename |- src/ |- packagename/ |- __init__.py |- yourfiles.py |- scripts/ |- non-exported python files }}} If you don't know what an `__init__.py` file is, we recommend that you read [[http://effbot.org/pyfaq/what-is-init-py-used-for.htm|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 [[http://pr.willowgarage.com/wiki/Manifest#head-622963aa58fac0f99d3aece21fc19bd0a05bfbd4|editing your manifest]]. See the next section for description of node files == 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 script, and having the main script's name == node's name. If your node is simple, this script 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/Version == Our target is Python 2.5, though we wish to make code that is easily transitioned to Python 2.6, 2.7, Python3k, etc... (see [[http://www.python.org/dev/peps/pep-3100/|PEP 3100]]). 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 "`!=`" (note: this doesn't mean "`<`" and "`>`" will be removed. Only "`<>`") * Use `from __future__ import division` so that you're using true division, not floor division [[http://www.python.org/dev/peps/pep-0238/|PEP 238]] * 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 * No `string.{atoi|atof|...}()`. Use `int()`, `float()` instead. * Avoid `print >> f, "Message"`. Use `f.write("Message\n")` instead (for instance, `sys.stderr.write("My error msg\n")`) 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. If you find one of your favorites on this list marked for death, please blame Guido. NOTE: the ROS python code base is still being transitioned to this style, so apologies for inconsistencies along the way.