2
votes

I have a problem trying to import cv2 in python3 when I run it from my home folder...

luis@luis-Ubuntu:~$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type
>>> 

but when I run python3 inside /usr/lib/python3/dist-packages or /usr/local/lib/python3.5/dist-packages path it works fine...

luis@luis-Ubuntu:~$ cd /usr/lib/python3/dist-packages
luis@luis-Ubuntu:/usr/lib/python3/dist-packages$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> 

I know this is related to include a path on the sys library, I added the export PYTHONPATH on my ~/.bashrc but didn't solve the problem...

export PYTHONPATH="/usr/local/lib/python3.5/dist-package‌​s:$PYTHONPATH"

I also found that if I insert the path before importing cv2 it works but I need to do this on all scripts or every time I run python3 from a terminal...

luis@luis-Ubuntu:~$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type
>>> import sys
>>> sys.path.insert(0,'/usr/lib/python3/dist-packages')
>>> import cv2
>>> 

but I want to fix this permanently, does anyone know how to solve this... btw... runs fine on python2...

3
Your export and insert use two different paths, perhaps making them same would be easier to debug. Also try echoing the PYTHONPATH after the export to see what's in there.hkchengrex
I tried this but didn't work:PYTHONPATH="$PYTHONPATH:/usr/local/lib/python3.5/dist-package‌​s/" export PYTHONPATH export PYTHONPATH="${PYTHONPATH}:/usr/lib/python3/dist-package‌​s/:/home/luis/" alias python3="/usr/bin/python3" export PYTHONPATH="/usr/local/lib/python3.5/dist-package‌​s:$PYTHONPATH"Luis Cazares
What if your print(sys.path) inside Python?hkchengrex
this what I got.Luis Cazares
['', '/usr/local/lib/python3.5/dist-package\u200c\u200bs', '/opt/ros/kinetic/lib/python2.7/dist-packages', '/usr/lib/python3/dist-package\u200c\u200bs', '/home/luis', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/usr/lib/python3.5/lib-dynload', '/home/luis/.local/lib/python3.5/site-packages', '/usr/local/lib/python3.5/dist-packages', '/usr/lib/python3/dist-packages'] >>>Luis Cazares

3 Answers

3
votes

From the print(sys.path) that you have provided,

...'/opt/ros/kinetic/lib/python2.7/dist-packages'...

I think the problem lies in this item. Although the python3 path also resides in sys.path, the python2.7 path precedes it. Python will catch the one in python2.7 first. When you are running in directly inside /python3/dist-packages, the current directory is placed first, and that precedes python2.7.

I think there are two ways:

  1. Remove python2.7/dist-packages from your PYTHONPATH
  2. Call sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages') before you import cv2. See this question.

The first approach should be the "proper" way but I am not sure how it is deal with if you want to use both python2/3 at the same time. You might be interested in this post.

1
votes

You can add the following two lines before you import cv2 in your python code. It works for me without changing any source file:

import sys
sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')

Then import cv2:

import cv2
0
votes

The root of this problem are the ROS commands like source/opt/ros/kinetic/setup.bash in the bashrc file /home/username/.bashrc , which force changes in the Python path. Even if you are not using ROS, the commands are still executed and thus you are directed to find cv2 in /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so in the ROS folder, which is not compatible with Python 3. More discussion on the same issue can be seen at: After install ROS Kinetic, cannot import OpenCV . Here I propose another solution which is not mentioned by any answer at that post.

The idea is to run source/opt/ros/kinetic/setup.bash(and any other bash related to ROS) only when using ROS. This way you do not have to modify .bashrc file (or editing the PYTHONPATH like to what you do) every time.

First, remove ROS-related commands like source/opt/ros/kinetic/setup.bash from the basrch file and make sure that you can import cv2 in Python 3.x with no error now.

Then, create a environment and install all the ROS related packages here. By doing so, we will have to activate this ros_environment when running ROS. For creating environment, see https://conda.io/docs/user-guide/tasks/manage-environments.html#creating-an-environment-with-commands

Next, activate your newly-created environment and follow https://conda.io/docs/user-guide/tasks/manage-environments.html#macos-and-linux to create files in the suggested path. Namely,

cd $CONDA_PREFIX
mkdir -p ./etc/conda/activate.d
mkdir -p ./etc/conda/deactivate.d
touch ./etc/conda/activate.d/env_vars.sh
touch ./etc/conda/deactivate.d/env_vars.sh

Edit the ./etc/conda/activate.d/env_vars.sh as follows

    source/opt/ros/kinetic/setup.bash

Also add in any other ROS-related bash in the file.

As for ./etc/conda/deactivate.d/env_vars.sh, what I do is exporting the PYTHONPATH back to Python 3. For example, it could be

    export PYTHONPATH="/usr/lib/python3/dist-packages"

Note that this is not really deactivating the source/opt/ros/kinetic/setup.bash command. I just found doing this way would direct my PYTHONPATH back to the default python 3, and the correct cv path can be found even after activation and deactivation of the ROS environment .