I've being updating a quaternions package for integration with numpy, so that it can be used in both python 2 and python 3. Unfortunately, the basic import step fails miserably with 3.x, though it has never failed with python 2.7. (I use python2.7 to compile the 2.7 version, and python3.x to compile the 3.x versions. It's a really simple distutils thing.) The error message doesn't even appear in google's results, and I just have no idea where to go from here.
Here is the complete output from a simple attempt to import the package:
> python -c 'import quaternion'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/mynamehere/.continuum/anaconda/envs/py3k/lib/python3.4/site-packages/quaternion/__init__.py", line 3, in <module>
from .numpy_quaternion import quaternion
TypeError: __import__() argument 1 must be str, not bytes
As the error message says, there is a line in __init__.py
saying
from .numpy_quaternion import quaternion
But why should that be problematic? There is a file numpy_quaternion.so
in the same directory as the __init__.py
file, which seems to contain the relevant symbols. Travis-CI shows that it works just fine in 2.7 (and the other tests pass), but fails in 3.2 and 3.4. So it's not just something wrong with my python installation. I tried to remove the .
for the relative import, but python couldn't find the numpy_quaternion
from which to import (not surprising). I tried changing it to from quaternion.numpy_quaternion
, but I get the same error.
I see that there have been changes to the import system in python 3, but if anything, I would have guessed that this would be more py3k-compliant than other ways of doing it. What's going wrong? How can I get this to work?
Just to clarify, my hierarchy looks like this:
.../site-packages/
quaternion/
__init__.py
numpy_quaternion.so
and the only thing that comes before the problematic line is import numpy as np
, which generally succeeds with no problem.
The python-list people got back to me right away with excellent suggestions. Turns out I was importing something within numpy_quaternion.so
(using the c-api), but the argument I was giving to that function was wrong. I was (basically) using code from a similar package:
PyObject* numpy_str = PyString_FromString("numpy");
PyObject* numpy = PyImport_Import(numpy_str);
I fixed it by using
PyObject* numpy = PyImport_ImportModule("numpy");
And as J. F. Sebastian points out in the comments, the reason that was going wrong for me was because that PyString_FromString
was just a #define
for the wrong function when I was using python 3.