Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Can't Encode Pic

2 views
Skip to first unread message

Carsten Haese

unread,
Nov 26, 2009, 10:03:12 AM11/26/09
to pytho...@python.org
Victor Subervi wrote:
> Hi;
> I have the following code:
>
> import cgitb; cgitb.enable()
> import cgi
> import MySQLdb
> from login import login
> user, passwd, db, host = login()
> db = MySQLdb.connect(host, user, passwd, db)
> cursor= db.cursor()
> form = cgi.FieldStorage()
> pic1 = form.getfirst('pic1')
> cursor.execute('update products set pic1=%s where ID=1;' % pic1)
>
> which throws the following error:
>
> [snip UnicodeDecodeErrors and various blind guesses...]
>
> Please advise.

The UnicodeDecodeErrors are a red herring. The real problem is that
you're using string interpolation (the %-operator) to pass the image
data to the database, so your code is force-feeding binary junk directly
into the query string. This results in an SQL query that's not
syntactically correct.

In order to pass values to the database safely, you need to use
parameter binding. In this case, that'll look something like this:

cursor.execute('update products set pic1=%s where ID=1',
(MySQLdb.Binary(pic1),))

[That comma between the two closing parentheses is not a typo. Do not
leave it out!]

Note that I'm not using string interpolation to shoehorn the picture
contents into the query string. I'm passing two arguments to
cursor.execute(). The first is the query template, with a %s placeholder
for your image contents. (Note that the query template is a plain ASCII
string, so all your Unicode-related problems will disappear in a puff of
magic.) The second argument is a tuple containing the actual parameters
to be filled into the query by the database engine. This query needs
only one parameter, so I'm making a 1-tuple containing the picture
contents, wrapped inside a MySQLdb.Binary object to tell the database
that this is a binary object.

Hope this helps,

--
Carsten Haese
http://informixdb.sourceforge.net

MRAB

unread,
Nov 26, 2009, 11:52:20 AM11/26/09
to pytho...@python.org
Victor Subervi wrote:

> On Thu, Nov 26, 2009 at 10:03 AM, Carsten Haese <carste...@gmail.com
> <mailto:carste...@gmail.com>> wrote:
>
> cursor.execute('update products set pic1=%s where ID=1',
> (MySQLdb.Binary(pic1),))
>
> [That comma between the two closing parentheses is not a typo. Do not
> leave it out!]
>
>
> A problem occurred in a Python script. Here is the sequence of function
> calls leading up to the error, in the order they occurred.
> /var/www/html/angrynates.com/cart/addEdit.py
> <http://angrynates.com/cart/addEdit.py>
> 85 print '<body>\n</html>'
> 86 db.commit()
> 87 cursor.close()
> 88
> 89 addEdit()
> addEdit = <function addEdit>
> /var/www/html/angrynates.com/cart/addEdit.py
> <http://angrynates.com/cart/addEdit.py> in addEdit()
> 66 id = 0
> 67 cursor.execute(sql)
> 68 cursor.execute('update products set pic1=%s where ID=1'
> (MySQLdb.Binary(pics[0]),))
> 69 for col in colNamesPics:
> cursor = <MySQLdb.cursors.Cursor object>, cursor.execute = <bound method
> Cursor.execute of <MySQLdb.cursors.Cursor object>>, global MySQLdb =
> <module 'MySQLdb' from
> '/usr/lib64/python2.4/site-packages/MySQLdb/__init__.pyc'>,
> MySQLdb.Binary = <function Binary>, pics =
> ['\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x01\x00H\x00H\x00\x00\xff\xe1\x13\xd5Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x07\x01\x12\x00\x03\x00\x00\x00\x01...\xdb\x9f\x94\xa9\xfds\xc9y\xb1W\xda\xd66\x9azS\x84\xd1\x1f\x93\xa9\xfdG\x0fm\xe3\x84\x01\xc5\x94\xfc\x88\xcf\x06f\xc5_\x7fPS6x\x076*\xff\x00\xff\xd9',
> '', '']
>
> TypeError: 'str' object is not callable
> args = ("'str' object is not callable",)
>
> Please advise.

On line 68 you have a string literal immediately followed by a tuple, so
it looks like you're trying to call a string, hence the exception. Put a
comma between the string literal and the tuple.

Carsten Haese

unread,
Nov 26, 2009, 1:52:45 PM11/26/09
to pytho...@python.org
Victor Subervi wrote:
> Hang on. Not done yet. The line of code I gave you was just a test case.
> The real ones, and the error they threw, follows:
> [...]
> 73 cursor.execute(sql, (MySQLdb.Binary(pics[id]),))
> [...]
>
> TypeError: list indices must be integers
> args = ('list indices must be integers',)
>
> Please advise,

I know the answer, but I'm not going to spoon-feed it to you this time,
since even a mediocre programmer should be able to figure this one out,
and you really need to start thinking for yourself if you ever want to
grow as a programmer.

How much time did you spend trying to figure out what that error message
is telling you? What thought processes, if any, have you followed?

MRAB

unread,
Nov 26, 2009, 2:12:04 PM11/26/09
to pytho...@python.org
Victor Subervi wrote:
> On Thu, Nov 26, 2009 at 1:10 PM, Victor Subervi <victor...@gmail.com
> <mailto:victor...@gmail.com>> wrote:

>
> On Thu, Nov 26, 2009 at 11:52 AM, MRAB <pyt...@mrabarnett.plus.com
> <mailto:pyt...@mrabarnett.plus.com>> wrote:
>
> Victor Subervi wrote:
>
> On Thu, Nov 26, 2009 at 10:03 AM, Carsten Haese
> <carste...@gmail.com <mailto:carste...@gmail.com>
> <mailto:carste...@gmail.com
> Hang on. Not done yet. The line of code I gave you was just a test case.
> The real ones, and the error they threw, follows:
>
> A problem occurred in a Python script. Here is the sequence of function
> calls leading up to the error, in the order they occurred.
> /var/www/html/angrynates.com/cart/addEdit.py
> <http://angrynates.com/cart/addEdit.py>
> 87 print '<body>\n</html>'
> 88 db.commit()
> 89 cursor.close()
> 90
> 91 addEdit()

> addEdit = <function addEdit>
> /var/www/html/angrynates.com/cart/addEdit.py
> <http://angrynates.com/cart/addEdit.py> in addEdit()
> 71 for pic in pics:
> 72 sql = 'update %s set %s=%s where ID=%s;' % (t,
> colNamesPics[i], '%s', str(id))

> 73 cursor.execute(sql, (MySQLdb.Binary(pics[id]),))
> 74 i += 1
> 75 elif whatDo == 'insert':

> cursor = <MySQLdb.cursors.Cursor object>, cursor.execute = <bound method
> Cursor.execute of <MySQLdb.cursors.Cursor object>>, sql = 'update
> products set pic1=%s where ID=1;', global MySQLdb = <module 'MySQLdb'
> from '/usr/lib64/python2.4/site-packages/MySQLdb/__init__.pyc'>,
> MySQLdb.Binary = <function Binary>, pics =
> ['\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x01\x00H\x00H\x00\x00\xff\xe1\x13\xd5Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x07\x01\x12\x00\x03\x00\x00\x00\x01...\xdb\x9f\x94\xa9\xfds\xc9y\xb1W\xda\xd66\x9azS\x84\xd1\x1f\x93\xa9\xfdG\x0fm\xe3\x84\x01\xc5\x94\xfc\x88\xcf\x06f\xc5_\x7fPS6x\x076*\xff\x00\xff\xd9'],
> id = '1'

>
> TypeError: list indices must be integers
> args = ('list indices must be integers',)
>
The traceback explains what the problem is: you're indexing a list, but
the index you're providing isn't an integer.

Remember that an integer is not a string and a string is not an integer.

Message has been deleted

Rami Chowdhury

unread,
Nov 27, 2009, 9:02:23 AM11/27/09
to Victor Subervi, pytho...@python.org, Dennis Lee Bieber
On Fri, Nov 27, 2009 at 02:59, Victor Subervi <victor...@gmail.com> wrote:
> On Thu, Nov 26, 2009 at 5:08 PM, Dennis Lee Bieber <wlf...@ix.netcom.com>
> wrote:
>> Nothing hinting at having
>> opened an interactive Python console and typing statements into it as an
>> experiment to see what may work, or what changes may break something.
>
> Please explain how this makes a difference. If I have the error in hand from
> trying to run the code through the Web--either printed to screen or gathered
> from the errors log--what need of opening the python interpreter

If you are content to run your code through the Web, and iterate
through versions of it there, then that's up to you. I'd suggest using
the interactive interpreter when you can, though -- most Python
programmers that I have encountered find it extremely helpful. In
particular, it can be invaluable in examining short snippets of code
-- such as the segments that are giving you trouble -- without
rerunning the whole program.

When I am debugging errors such as this, what I typically do is snip
out the particular bit that is causing the problem and run it in the
interactive interpreter, experimenting with changes to it until it
works as I want it to. Perhaps such a method would help you in
debugging as well? Certainly it would enable you to give the list a
little more information about what you have and haven't tried when
coming here with a problem...

Carsten Haese

unread,
Nov 27, 2009, 11:13:59 AM11/27/09
to pytho...@python.org
Victor Subervi wrote:
> The difficulty I am having is that for
> some reason it's not inserting. The form inserts the first image but not
> the second.

My guess is that you're not calling db.commit() after inserting the
second image. (If you had shown your code, I wouldn't have to guess.)

HTH,

Message has been deleted

Carsten Haese

unread,
Nov 27, 2009, 2:21:30 PM11/27/09
to pytho...@python.org
Victor Subervi wrote:

> On Fri, Nov 27, 2009 at 12:13 PM, Carsten Haese <carste...@gmail.com
> <mailto:carste...@gmail.com>> wrote:
>
> Victor Subervi wrote:
> > The difficulty I am having is that for
> > some reason it's not inserting. The form inserts the first image
> but not
> > the second.
>
> My guess is that you're not calling db.commit() after inserting the
> second image. (If you had shown your code, I wouldn't have to guess.)
>
>
> That was the logical guess and yes, it hit the target. I should have
> known better. Thank you.
> Now, I have this line of code on another page that calls the images once
> the database is populated:
>
> print '<img src="getpic.py?pic=%d&id=%d"
> width="100"></td>\n' % (a, w)
>
> This is looped through for every value of pic/id returned from the
> database, producing the following code on the Web page:
>
> <img src="getpic.py?pic=1&id=1" width="100"></td>
> <img src="getpic.py?pic=1&id=2" width="100"></td>
>
> The problem here is that only one of the images prints on the said page!
> However, if I surf to those URLs, the images appear!

Are you sure that you're surfing to *exactly* those URLs? When I go to
http://www.angrynates.com/cart/getpic.py?pic=2&id=1, I get an image, but
when I go to http://www.angrynates.com/cart/getpic.py?pic=1&id=2, I get
an error message. I am guessing that you have your pic and id parameter
switched around.

> Is it possible that
> because I'm passing values to the variables and perhaps simultaneously
> calling the script, that it can only fulfill the first request?

That's possible if your script is doing something stupid, but I find my
above guess much more likely.

0 new messages