Note: This tutorial assumes that you have completed the previous tutorials: ROS tutorials. |
Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Setting Up Your PYTHONPATH
Description: What to do to find other python modulesTutorial Level: BEGINNER
Next Tutorial: Using numpy with rospy
Contents
Commonly in python, when you use another python module, you use:
import foo
in your python code and it is up to the user of your code to make sure module "foo" is in his PYTHONPATH. In ROS, it is important that people can install multiple ROS libraries side-by-side on the same computer. That means there may be two different modules "foo", and the right one needs to be in the PYTHONPATH.
The module "roslib" allows this situation, it will search for a ROS package in your current ROS_PACKAGE_PATH, and make sure that the python modules can be imported.
You have already written a manifest.xml file that declares your dependencies, so ROS will use this same manifest file to help you set your PYTHONPATH (we try to use the DRY -- Don't Repeat Yourself -- principle as much as possible).
This is all you need to do:
Make sure that your dependencies are properly listed in your Manifest
Add the following line to the top of your Python code:
import roslib; roslib.load_manifest('your_package_name') import foo
So if you declared the package of module foo in your manifest.xml, the line import foo will work after the roslib.load_manifest call.
NOTE: This line doesn't need to go at the top of every Python file; they just need to go at the top of any file that is a 'main' entry point.
roslib will load up your manifest file and set sys.path to point to the appropriate directory in every package you depend on. These two lines work because roslib is required to be on the PYTHONPATH of every ROS user.
Example
For this example we create a new package and try to reuse the message Num that we defined in our beginner_tutorials package:
For rosbuild we create a new package in our sandbox:
$ roscd $ cd sandbox $ roscreate-pkg listener_extend rospy beginner_tutorials
This should already put the dependency to beginner_tutorials in our manifest.xml file:
$ cat listener_extend/manifest.xml ... <depend package="rospy"/> <depend package="beginner_tutorials"/> ...
Next we create a node using the message defined in beginner_tutorials. Create a diretory nodes first:
$ cd listener_extend $ mkdir nodes
In the nodes directory, create a file listener_extend.py with these contents:
Make this file executable and run it:
$ chmod u+x nodes/listener_extend.py $ nodes/listener_extend.py num: 0
As you can see, the Num module of beginner tutorials was successfully found even though it is not on your PYTHONPATH.
In ROS versions earlier than ROS Groovy, a library called roslib achieved this for us.
With catkin, python imports are done without roslib:
import foo
Catkin sets up PYTHONPATH in your catkin workspace and some relay files so that this works even with two python modules in your src folder. So if you have two modules in your catkin workspace, where one depends on the other, you need to configure and build the modules first, and then you can run them.
Example
For this example we create a new package and try to reuse the message Num that we defined in our beginner_tutorials package:
For catkin we create a new package in our source folder:
$ cd catkin_ws/src $ catkin_create_pkg listener_extend rospy beginner_tutorials
Next we create a node using the message defined in beginner_tutorials. Create a diretory nodes first:
$ cd listener_extend $ mkdir nodes
In the nodes directory, create a file listener_extend.py with these contents:
Note that in comparison to rosbuild, no roslib call is required.
Make this file executable and run it:
$ chmod u+x nodes/listener_extend.py $ python nodes/listener_extend.py num: 0
If this fails,make sure you have run
$ source ~/catkin_ws/devel/setup.bash
before executing nodes/listener_extend.py
As you can see, the Num module of beginner_tutorials was successfully.