ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
5

How do I install a Python module with a different name than the catkin package?

asked 2013-03-25 12:42:10 -0500

joq gravatar image

updated 2014-01-28 17:15:53 -0500

ngrennan gravatar image

My package is named camera_info_manager_py, but the Python module is camera_info_manager.

With rosbuild that was easy: just create a src/camera_info_manager.py script, and dependent packages could import it directly.

With catkin I can't figure out how to make it work. For API compatibility with earlier releases, I prefer not to rename the module camera_info_manager_py (which does work).

I suppose I could add that module to the camera_info_manager package, and make camera_info_manager_py depend on it for compatibility. But, that would be a hassle, and not relevant to the many users of the C++ camera_info_manager package.

EDIT: Thanks, William. I had tried the py_modules, and as you noted, it did not work. I didn't realize that was caused by a missing feature.

I do not fully understand your recommended work-around. Would the script go in src/camera_info_manager.py, as it did before? I was not able to figure out how to resolve that in the PYTHONPATH.

For compatibility, other packages need to do this:

import camera_info_manager
cinfo = camera_info_manager.CameraInfoManager()

or:

from camera_info_manager import *
cinfo = CameraInfoManager()

I still don't see how to make that happen.

EDIT2: I did (almost) exactly as you recommended, but catkin installs no camera_info_manager package.

$ roscd
$ catkin_make
$ cd build
$ make install
$ ls -l ../install/lib/python2.7/dist-packages/
total 20
drwxr-xr-x 3 joq joq 4096 Mar 26 16:59 ackermann_msgs
-rw-rw-r-- 1 joq joq  421 Mar 26 16:59 camera_info_manager_py-0.2.0.egg-info
drwxrwxr-x 2 joq joq 4096 Mar 26 16:59 unique_id
-rw-rw-r-- 1 joq joq  276 Mar 26 16:59 unique_id-1.0.1.egg-info
drwxr-xr-x 3 joq joq 4096 Mar 26 16:59 uuid_msgs

So, there is an egg-info for camera_info_manager_py, but no Python package.

$ make run_tests_camera_info_manager_py
-- run_tests.py: execute commands
  /opt/ros/groovy/bin/rostest --pkgdir=/home/joq/ros/wet/groovy/src/camera_info_manager_py --package=camera_info_manager_py --results-filename tests_unit_test.xml /home/joq/ros/wet/groovy/src/camera_info_manager_py/tests/unit_test.test
... logging to /home/joq/.ros/log/rostest-vision-4-5760.log
[ROSUNIT] Outputting test results to /home/joq/ros/wet/groovy/build/test_results/camera_info_manager_py/rostest-tests_unit_test.xml
Traceback (most recent call last):
  File "/home/joq/ros/wet/groovy/src/camera_info_manager_py/tests/test_camera_info_manager.py", line 17, in <module>
    from camera_info_manager import *
ImportError: No module named camera_info_manager
testtest_camera_info_manager_py ... FAILURE!

As you can see, the from camera_info_manager import * fails.

The only difference with what you recommended is that my src/camera_info_manager/__init__.py contains only this:

from .camera_info_manager import *

I did it that way because the camera_info_manager module was already careful not to define anything not needed by its users. I guess it is equivalent to putting the entire script inside __init__.py.

EDIT3: here's my current setup.py:

#!/usr/bin/env python

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

d = generate_distutils_setup(
    py_modules=['camera_info_manager'],
    package_dir={'': 'src'},
    install_requires=['yaml'],
    )

setup(**d)

EDIT4: yes, the install did show these errors:

+ cd /home/joq/ros/wet/groovy/src/camera_info_manager_py
+ /usr/bin/env PYTHONPATH=/home/joq/ros/wet/groovy/install/lib/python2.7/dist-packages:/home/joq/ros/wet/groovy/build/lib ...
(more)
edit retag flag offensive close merge delete

Comments

Is your repository up-to-date? https://github.com/jack-oquin/camera_info_manager_py/blob/master/setup.py Or is this an old setup.py

William gravatar image William  ( 2013-03-26 12:35:28 -0500 )edit

That is the old one. I have not committed these changes, because they don't work. The github one (which works) provides the camera_info_manager_py name, instead.

joq gravatar image joq  ( 2013-03-26 12:39:30 -0500 )edit

I could commit them to a new branch, if you want to experiment with it.

joq gravatar image joq  ( 2013-03-26 12:45:00 -0500 )edit

Your setup.py should be packages=['camera_info_manager'] not py_modules=['camera_info_manager']. Can you post the output from catkin_make install? I bet it has a message about not finding a py_module 'camera_info_manager'.

William gravatar image William  ( 2013-03-26 14:10:53 -0500 )edit

Changing it to packages worked! Now the tests run successfully, and the src/camera_info_manager directory contents get installed under dist-packages. Thanks for the help, William!

joq gravatar image joq  ( 2013-03-26 14:21:12 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
7

answered 2013-03-25 13:39:23 -0500

William gravatar image

updated 2013-03-26 07:06:12 -0500

You can tell the setup.py to install individual modules rather than packages:

http://docs.python.org/2/distutils/setupscript.html#listing-individual-modules

A setup.py for your example might look like this:

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

d = generate_distutils_setup(
    py_modules=['camera_info_manager'],
    package_dir={'': 'src'}
)

setup(**d)

When I was testing this I noticed that catkin warns:

*** Arguments ['py_modules'] to setup() not supported in catkin devel space in setup.py of camera_info_manager_py

This indicates to me that we never implemented support for this argument in devel spaces. We should support this, so I opened a ticket:

https://github.com/ros/catkin/issues/399

For now that means that if you want your package to work in the devel space then you should wrap it in a python package, and you can transparently do this using the package __all__ magic variable.

http://docs.python.org/2/tutorial/modules.html#importing-from-a-package

UPDATE:

Your current layout is:

src/
  camera_info_manager.py

And your setup.py might be:

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

d = generate_distutils_setup(
    py_modules=['camera_info_manager'],
    package_dir={'': 'src'}
)

setup(**d)

I would propose that you change your layout to this:

src/
  camera_info_manager/
    __init__.py
    camera_info_manager.py

And in the __init__.py:

from .camera_info_manager import CameraInfoManager, etc...
__all__ = ['CameraInfoManager', 'free_func1', 'another_class']

Users will still be able to do this:

import camera_info_manager
cinfo = camera_info_manager.CameraInfoManager()

Or

from camera_info_manager import *
cinfo = CameraInfoManager()

But they will also be able to do this:

from camera_info_manager.camera_info_manager import CameraInfoManager
cinfo = CameraInfoManager()

And your setup.py:

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

d = generate_distutils_setup(
    packages=['camera_info_manager'],
    package_dir={'': 'src'}
)

setup(**d)
edit flag offensive delete link more

Question Tools

Stats

Asked: 2013-03-25 12:42:10 -0500

Seen: 10,117 times

Last updated: Mar 26 '13