views:

121

answers:

2

I ran across this bug three times today in one of our projects. Putting the problem and solution online for future reference.

impost psycopg2

con = connect(...)

def save(long_blob):
     cur = con.cursor() 
     long_data = struct.unpack('<L', long_blob)
     cur.execute('insert into blob_records( blob_data ) values (%s)', [long_data])

This will fail with the error "can't adapt" from psycopg2.

A: 

The problem is struct.unpack returns a tuple result, even if there is only one value to unpack. You need to make sure you grab the first item from the tuple, even if there is only one item. Otherwise psycopg2 sql argument parsing will fail trying to convert the tuple to a string giving the "can't adapt" error message.

impost psycopg2

con = connect(...)

def save(long_blob):
     cur = con.cursor() 
     long_data = struct.unpack('<L', long_blob)

     # grab the first result of the tuple
     long_data = long_data[0]

     cur.execute('insert into blob_records( blob_data ) values (%s)', [long_data])
Great Turtle
A: 

"Can't adapt" is raised when psycopg doesn't know the type of your long_blob variable. What type is it?

You can easily register an adapter to tell psycopg how to convert the value for the database.

Because it is a numerical value, chances are that the AsIs adapter would already work for you.

piro
In this case my type was a binary string, but contained within the tuple returned by struct.unpack. Something like ('0x001122') instead of '0x001122' by itself. I suppose we could make a tuple extractor, but for now this just documents our mistake. Thanks for the answer.
Great Turtle