While working on ROS package for Anki Vector I had no choice but to use Python 3.6 as Anki’s Python SDK was specifically built for that version. Doing so I found that setting up ROS with Python 3 isn’t such a trivial task. It’s also not extremely complex, but there is no single guide that says exactly how to do it properly — so I decided to write one. This guide was written for ROS Melodic but a lot of it applies also for Kinetic.

In case you just started to build your Python 3 package and you want to make sure you’ve fixed all of the issues we're going to discuss beforehand, you can use a small ROS Package I wrote to reproduce them and see.

Also— ROS works best with Python 2 (as you probably know if you’re reading this), ROS2, on the other hand, was built with Python 3 in mind. So if you don’t need ROS(1) specifically but rather simply interested in developing for ROS using Python 3 you should consider moving to ROS2. Otherwise, follow these steps:

1. Basic Setup

Once you try to execute some script with python 3 shebang line(#!/usr/bin/env python3) you are going the get the following screaming error about some missing yaml library:

Traceback (most recent call last):

File "/catkin_ws/src/ros_python3_issues/src/issue_yaml.py", line 3, in <module>

import rospy

File "/opt/ros/melodic/lib/python2.7/dist-packages/rospy/__init__.py", line 47, in <module>

from std_msgs.msg import Header

File "/opt/ros/melodic/lib/python2.7/dist-packages/std_msgs/msg/__init__.py", line 1, in <module>

from ._Bool import *

File "/opt/ros/melodic/lib/python2.7/dist-packages/std_msgs/msg/_Bool.py", line 5, in <module>

import genpy

File "/opt/ros/melodic/lib/python2.7/dist-packages/genpy/__init__.py", line 34, in <module>

from . message import Message, SerializationError, DeserializationError, MessageException, struct_I

File "/opt/ros/melodic/lib/python2.7/dist-packages/genpy/message.py", line 44, in <module>

import yaml

ModuleNotFoundError: No module named 'yaml'

Don’t worry, open bash and install the following missing libraries:

sudo apt-get install python3-pip python3-yaml

sudo pip3 install rospkg catkin_pkg

And that’s it! now try executing your script again…

2. cv_bridge Issue

If you’ll try to use cv_bridge for OpenCV you are most likely to get the following exception:

Traceback (most recent call last):

File "/catkin_ws/src/ros_python3_issues/src/issue_cv_bridge.py", line 23, in <module>

ros_image = bridge.cv2_to_imgmsg(numpy.asarray(empty_image), encoding="rgb8") # convert PIL image to ROS image

File "/opt/ros/melodic/lib/python2.7/dist-packages/cv_bridge/core.py", line 259, in cv2_to_imgmsg

if self.cvtype_to_name[self.encoding_to_cvtype2(encoding)] != cv_type:

File "/opt/ros/melodic/lib/python2.7/dist-packages/cv_bridge/core.py", line 91, in encoding_to_cvtype2

from cv_bridge.boost.cv_bridge_boost import getCvType

ImportError: dynamic module does not define module export function (PyInit_cv_bridge_boost)

The issue is that cv_bridge is built only for python 2.7 so our python 3 interpreter is trying to use cv_bridge for 2.7 and fails, lets built it for Python 3:

First, let's install some tools we’ll need for the build process

sudo apt-get install python-catkin-tools python3-dev python3-numpy

Now, create new catkin_build_ws to avoid any future problems with catkin_make(assuming you are using it) and config catkin to use your python 3(3.6 in my case) when building packages:

mkdir ~/catkin_build_ws && cd ~/catkin_build_ws

catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3 -DPYTHON_INCLUDE_DIR=/usr/include/python3.6m -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.6m.so

catkin config --install

clone official vision_opencv repo:

mkdir src

cd src

git clone -b melodic https://github.com/ros-perception/vision_opencv.git

finally, let’s build and source the package:

cd ~/catkin_build_ws

catkin build cv_bridge

source install/setup.bash --extend

That’s it! now you can use cv_bridge from Python 3!

3. rostest Issue

... logging to /root/.ros/log/rostest-477a6ee2f64d-4170.log

[ROSUNIT] Outputting test results to /root/.ros/test_results/ros_python3_issues/rostest-test_test_issue_rosunit.xml

Traceback (most recent call last):

File "/catkin_ws/src/ros_python3_issues/test/issue_rosunit.py", line 18, in <module>

rostest.rosrun('ros_python3_issues', 'issue_rosunit', TestROSUnitIssue)

File "/opt/ros/melodic/lib/python2.7/dist-packages/rostest/__init__.py", line 146, in rosrun

result = rosunit.create_xml_runner(package, test_name, result_file).run(suite)

File "/opt/ros/melodic/lib/python2.7/dist-packages/rosunit/xmlrunner.py", line 275, in run

result.print_report(stream, time_taken, out_s, err_s)

File "/opt/ros/melodic/lib/python2.7/dist-packages/rosunit/xmlrunner.py", line 202, in print_report

stream.write(ET.tostring(self.xml(time_taken, out, err).getroot(), encoding='utf-8', method='xml'))

TypeError: write() argument must be str, not bytes

[Testcase: testissue_rosunit] ... ok [ROSTEST]----------------------------------------------------------------------- SUMMARY

* RESULT: SUCCESS

* TESTS: 0

* ERRORS: 0

* FAILURES: 0

This issue was actually already solved but for some reason, it is not yet available on the apt repository so we’ll simply install it from source:

That’s it!

Found any other issue with ROS running Python 3 that I didn’t mention? Please, DM or email(beta_b0t@yahoo.com) me and I will update this post(with credits of course 😉).

References: