Pickling a dictionary into a PostgreSQL database?

1,215 views
Skip to first unread message

teth

unread,
Jan 15, 2009, 11:17:01 AM1/15/09
to Django users
Hello, I pickled a dictionary and stored it in my database like this:
article.rating = article.rating + 1
ratings[request.user.username] = 1
article.rating_list = pickle.dumps(ratings)
article.save()

ratings looks like this:
{'froob': 1, 'alik': 1, 'teth': 1}

When I try and load the pickled string from the database it gives me
the following error:
KeyError at /article/testing123/up/
'\x00'

article/testing123 loads the article testing123 from the database and
the /up/ is to improve the rating of it. The dictionary is to prevent
users from rating the same article twice by putting their username as
an index in a dictionary. What am I doing wrong? (The pickled string
is stored in a TEXT field)

Dj Gilcrease

unread,
Jan 15, 2009, 12:27:19 PM1/15/09
to django...@googlegroups.com
I would not use a dict like that, just uses more memory, I would
create a ArticleVote models, something like

http://dpaste.com/hold/109437/

I also show how I would use it in the views


Dj Gilcrease
OpenRPG Developer
~~http://www.openrpg.com

bruno desthuilliers

unread,
Jan 15, 2009, 12:39:07 PM1/15/09
to Django users
On 15 jan, 17:17, teth <godsinven...@gmail.com> wrote:
> Hello, I pickled a dictionary and stored it in my database like this:
> article.rating = article.rating + 1
> ratings[request.user.username] = 1
> article.rating_list = pickle.dumps(ratings)
> article.save()
>
> ratings looks like this:
> {'froob': 1, 'alik': 1, 'teth': 1}
>
> When I try and load the pickled string from the database it gives me
> the following error:
> KeyError at /article/testing123/up/
> '\x00'

Perhaps a bit informations would help. Like, what does the line of
code that raises looks like, and what does the field content looks
like ?

> article/testing123 loads the article testing123 from the database and
> the /up/ is to improve the rating of it. The dictionary is to prevent
> users from rating the same article twice by putting their username as
> an index in a dictionary. What am I doing wrong?

As far as I'm concerned, I'd answer that the obvious problem here is
storing a serialized dict into a db field, instead of properly using a
item/user table. But I guess this is not the answer you expect !-)

> (The pickled string
> is stored in a TEXT field)

Isn't pickle a binary format ?

Sorry, not really helpful, I'm afraid.

Torsten Bronger

unread,
Jan 15, 2009, 1:00:43 PM1/15/09
to django...@googlegroups.com
Hallöchen!

teth writes:

> [...]


>
> When I try and load the pickled string from the database it gives me
> the following error:
> KeyError at /article/testing123/up/
> '\x00'

I do the same thing, and I remember that I was forced to write
"pickle.loads(str(database_text))" (note the str()). However, I
don't remember the exception I was confronted with.

Tschö,
Torsten.

--
Torsten Bronger, aquisgrana, europa vetus
Jabber ID: torsten...@jabber.rwth-aachen.de

teth

unread,
Jan 18, 2009, 8:29:47 AM1/18/09
to Django users
Using str(pickle.dumps()) and the pickle.loads(str()) works perfectly.

The reason I use a dict instead of a list is because I can add an
entry that does not come in numeric order (with a list you cannot add
an item to it simply by list[32] if the list is not that long).

I used a dict because it is very fast to run if rating['froob'] == 1.
Also it simplifies the database models.

On Jan 15, 1:00 pm, Torsten Bronger <bron...@physik.rwth-aachen.de>
wrote:
> Hallöchen!
>
> teth writes:
> > [...]
>
> > When I try and load the pickled string from thedatabaseit gives me
> > the following error:
> > KeyError at /article/testing123/up/
> > '\x00'
>
> I do the same thing, and I remember that I was forced to write
> "pickle.loads(str(database_text))" (note the str()).  However, I
> don't remember the exception I was confronted with.
>
> Tschö,
> Torsten.
>
> --
> Torsten Bronger, aquisgrana, europa vetus
>                    Jabber ID: torsten.bron...@jabber.rwth-aachen.de

Torsten Bronger

unread,
Jan 21, 2009, 10:07:58 AM1/21/09
to django...@googlegroups.com
Hallöchen!

teth writes:

> Using str(pickle.dumps()) and the pickle.loads(str()) works
> perfectly.

Unfortunately, I had to realise that it is not so simple due to
<http://bugs.python.org/issue2980>. Now it use the following
functions:

def ascii_pickle(python_object):
u"""Converts an arbitrary Python object to an ASCII-only string to be
written to the database. Unfortunately, even protocol 0 of Python's
``pickle`` module may emit non-ASCII characters, see
<http://bugs.python.org/issue2980>. However, this is dangerous since the
database expects Unicode strings and can't decode such octet strings.
Therefore, this routine does another encoding step using base64. This
makes debugging slightly more difficult, but there we go.

:Parameters:
- `python_object`: the object instance to be pickled

:type python_object: object

:Return:
the ASCII-only string representing the object instance

:rtype: str
"""
# FixMe: Maybe instead of base64 another encoder should be used that keeps
# the string largely readable.
return base64.b64encode(pickle.dumps(python_object, protocol=2))


def ascii_unpickle(string):
u"""This is the inverse function of `ascii_pickle`.

:Parameters:
- `string`: the ASCII-only database string to be unpickled

:type string: str

:Return:
the original Python object instance that was represented by the string

:rtype: object
"""
return pickle.loads(base64.b64decode(string))

Tschö,
Torsten.

--
Torsten Bronger, aquisgrana, europa vetus

Jabber ID: torsten...@jabber.rwth-aachen.de

teth

unread,
Jan 22, 2009, 6:52:40 PM1/22/09
to Django users
Thank you for the tip. I was actually in the middle of debugging a
problem which I think may have been solved by this post. I used
urlsafe_b64encode() and urlsafe_b64decode because a URL cannot contain
any non-ASCII characters (can it?). I could also have used the normal
b64 functions, but I wanted to be sure.

On Jan 21, 10:07 am, Torsten Bronger <bron...@physik.rwth-aachen.de>
wrote:
> Hallöchen!
>
> teth writes:
> > Using str(pickle.dumps()) and thepickle.loads(str()) works
> > perfectly.
>
> Unfortunately, I had to realise that it is not so simple due to
> <http://bugs.python.org/issue2980>.  Now it use the following
> functions:
>
> def ascii_pickle(python_object):
>     u"""Converts an arbitrary Python object to an ASCII-only string to be
>     written to thedatabase.  Unfortunately, even protocol 0 of Python's
>     ``pickle`` module may emit non-ASCII characters, see
>     <http://bugs.python.org/issue2980>.  However, this is dangerous since the
>    databaseexpects Unicode strings and can't decode such octet strings.
>     Therefore, this routine does another encoding step using base64.  This
>     makes debugging slightly more difficult, but there we go.
>
>     :Parameters:
>       - `python_object`: the object instance to be pickled
>
>     :type python_object: object
>
>     :Return:
>       the ASCII-only string representing the object instance
>
>     :rtype: str
>     """
>     # FixMe: Maybe instead of base64 another encoder should be used that keeps
>     # the string largely readable.
>     return base64.b64encode(pickle.dumps(python_object, protocol=2))
>
> def ascii_unpickle(string):
>     u"""This is the inverse function of `ascii_pickle`.
>
>     :Parameters:
>       - `string`: the ASCII-onlydatabasestring to be unpickled
>
>     :type string: str
>
>     :Return:
>       the original Python object instance that was represented by the string
>
>     :rtype: object
>     """
>     returnpickle.loads(base64.b64decode(string))
>
> Tschö,
> Torsten.
>
> --
> Torsten Bronger, aquisgrana, europa vetus
>                    Jabber ID: torsten.bron...@jabber.rwth-aachen.de
Reply all
Reply to author
Forward
0 new messages