Rakesh
Rakesh

Reputation: 4127

Cython extension not compatible with Python2.

I am using a Cython Extension code but this code throw error:

/Users/rkumar/src/fast-geohash/cython/_fast_geohash.pyx in _fast_geohash.encode()
     56                 ch = 0
     57
---> 58         return result[:i].decode('ascii')
     59     finally:
     60         free(result)

TypeError: Expected str, got unicode

I don't get this error on Python 3. I want to use this extension on Python2. I don't know how to fix this. Here is the extension code:

cpdef str encode(double latitude, double longitude, int precision=12):
    """
    Encode a position given in float arguments latitude, longitude to
    a geohash which will have the character count precision.
    """
    cdef (double, double) lat_interval
    cdef (double, double) lon_interval
    lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
    cdef char* result = <char *> malloc((precision + 1) * sizeof(char))
    if not result:
        raise MemoryError()
    result[precision] = '\0'
    cdef int bit = 0
    cdef int ch = 0
    even = True
    cdef int i = 0
    try:
        while i < precision:
            if even:
                mid = (lon_interval[0] + lon_interval[1]) / 2
                if longitude > mid:
                    ch |= bits[bit]
                    lon_interval = (mid, lon_interval[1])
                else:
                    lon_interval = (lon_interval[0], mid)
            else:
                mid = (lat_interval[0] + lat_interval[1]) / 2
                if latitude > mid:
                    ch |= bits[bit]
                    lat_interval = (mid, lat_interval[1])
                else:
                    lat_interval = (lat_interval[0], mid)
            even = not even
            if bit < 4:
                bit += 1
            else:
                result[i] = __base32[ch]
                i += 1
                bit = 0
                ch = 0

        return result[:i].decode('ascii')
    finally:
        free(result)

Upvotes: 0

Views: 193

Answers (1)

DavidW
DavidW

Reputation: 30927

Python 2 str == Python 3 bytes

Python 2 unicode == Python 3 str.

Cython converts your C char[] to str on Python 2 and bytes on Python 3 (since this is the most logical conversion in both cases).

On Python 2, str.decode returns a unicode object. You get an error because it doesn't match the str object in the function signature. On Python 3 bytes.decode returns a str object (equivalent to a Python 2 unicode object). This matches the str in the function signature, and so is fine.

The easiest solution is to stop specifying the return type in the function signature - there is rarely much benefit to be gained from specifying the exact type of Python objects:

cpdef encode(double latitude, double longitude, int precision=12):

Upvotes: 1

Related Questions