Reputation: 1787
I compiled my test.thrift file using:
thrift -gen py test.thrift
Then i tried to import the created files:
from test.ttypes import *
When I use Python 2.7 the import works but with Python 3.4 it raises
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/art/SerTest/addressThrift/gen-py/test/ttypes.py", line11, in <module>
from thrift.transport import TTransport
File "/usr/local/lib/python3.4/dist-
packages/thrift/transport/TTransport.py", line 20, in <module>
from cStringIO import StringIO
ImportError: No module named 'cStringIO'
I tried to run:
sudo python3 setup.py install
and got many exceptions, all seems to be related to python 2 vs 3 problems. for example:
File "/usr/local/lib/python3.4/dist-
packages/thrift/transport/TSSLSocket.py", line 99
except socket.error, e:
^
SyntaxError: invalid syntax
I addition there is a warning thats seems important:
/usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'use_2to3'
Googling Thrift Python 3 support seems contradicting.
Those say that there is no support:
Does cql support python 3?
https://issues.apache.org/jira/browse/THRIFT-1857
And here I understand from the subtext that it does:
Thrift python 3.4 TypeError: string argument expected, got 'bytes'
Python 3.4 TypeError: input expected at most 1 arguments, got 3
https://issues.apache.org/jira/browse/THRIFT-2096
So does Thrift support Python 3.X? If so what did I missed?
Upvotes: 8
Views: 11654
Reputation: 357
It seems that thrift 0.10.0, released in January 2017, already has built-in support for Python 2 and 3 at the same time, but beware there are some compatibility issues.
Sources:
Upvotes: 3
Reputation: 5286
Install thrift with pip3 to make sure it gets converted (I think they use 2to3) and it will use the python3 syntax except ExceptionName as e
as well as other python3 syntax like turning print into a function, ...
However, there are still some bugs. I found that pack()
results are used as input to a StringIO
as in python2 it returns a str
but in python3 it was changed so that it returns a bytes
. The easiest solution is to change the following files:
from io import StringIO
to (option 1)
from io import BytesIO as StringIO
or (option 2)
from io import BytesIO
buff = ''
to
buff = b''
self.__rbuf = StringIO("")
to
self.__rbuf = StringIO(b'')
Search every
StringIO
and replace it for
BytesIO
self.writeI32(len(str))
self.trans.write(str)
to
buff = bytes(str, 'utf-8')
self.writeI32(len(buff))
self.trans.write(buff)
str = self.trans.readAll(len)
to
str = self.trans.readAll(len).decode('utf-8')
I also made 2 functions that are equivalent to python2's pack()
and unpack()
for python3 that may be useful for some other problems where you can't just substitute the io for the proper one:
from io import pack, unpack
def packStr(fmt, v):
return "".join(["\\x{:02x}".format(i) for i in list(pack(fmt, v))])
def unpackStr(fmt, v):
return unpack(fmt, bytes([int(i, 16) for i in v.split("\\x")[1:]]))
Upvotes: 4
Reputation: 649
There is a better solution to this. Instead of waiting the official python 3 support, why not use our python implementation of thrift?
https://github.com/eleme/thriftpy
it fully supports python 3, and pypy, and pypy3.
Upvotes: 7