[Tutor] Handling a Unicode Return using Pyodbc
Tim Golden
mail at timgolden.me.uk
Tue Nov 15 10:16:56 CET 2011
On 14/11/2011 21:43, Tony Pelletier wrote:
> Good Afternoon,
>
> I'm writing a program that is essentially connecting to MS SQL Server
> and dumping all the contents of the tables to separate csv's. I'm
> almost complete, but now I'm running into a Unicode issue and I'm not
> sure how to resolve it.
>
> I have a ridiculous amount of tables but I managed to figure out it was
> my Contact and a contact named Robert Bock. Here's what I caught.
>
> (127, None, u'Robert', None, u'B\xf6ck', 'uCompany Name', None, 1, 0,
> 327, 0)
>
> The u'B\xf6ck' is actually Böck. Notice the ö
>
> My problem is I'm not really sure how to handle it and whether or not
> it's failing on the query or the insert to the csv. The Exception is:
>
> 'ascii' codec can't encode character u'\xf6' in position 1: ordinal not
> in range(128)
Thanks for producing a thinned-down example. If I may take this at
face value, I assume you're doing something like this:
<code>
import csv
#
# Obviously from database, but for testing...
#
data = [
(127, None, u'Robert', None, u'B\xf6ck', 'uCompany Name', None, 1, 0,
327, 0),
]
with open ("temp.csv", "wb") as f:
writer = csv.writer (f)
writer.writerows (data)
</code>
which gives the error you describe.
In short, the csv module in Python 2.x (not sure about 3.x) is
unicode-unaware. You're passing it a unicode object and it's got no way
of knowing what codec to use to encode it. So it doesn't try to guess:
it just uses the default (ascii) and fails.
And this is where it gets just a little bit messy. Depending on how much
control you have over your data and how important the unicodeiness of it
is, you need to encode things explicitly before they get to the csv module.
One (brute force) option is this:
<code snippet>
def encoded (iterable_of_stuff):
return tuple (
(i.encode ("utf8") if isinstance (i, unicode) else i)
for i in iterable_of_stuff
)
#
# ... other code
#
writer.writerows ([encoded (row) for row in data])
</code snippet>
This will encode anything unicode as utf8 and leave everything else
untouched. It will slow down your csv generation, but that might well
not matter (especially if you're basically IO-bound).
TJG
More information about the Tutor
mailing list