Acentos , python y pymssql

1,414 views
Skip to first unread message

Carlos Herrera Polo

unread,
Jul 16, 2012, 12:57:31 PM7/16/12
to pytho...@googlegroups.com
Estimados:

Quisiera por favor si fuera posible alguien me aclare un problema que tengo con python, ldap, pymssql y los acentos....

El asunto es el siguiente:

Tengo un servidor con Active Directory (Windows 2003), desde python desarrolle una funcion utilizando la libreria "ldap" para conectarme al servidor y hacer consultas, funciona perfecto.

La idea es la siguente:

Tengo una funcion que tiene como algumento la cuenta de usuario, esta funcion me retorna el nombre completo de ese usuario en el active directory, por ejemplo:

nombre_completo('jperez')

Retorna : José Perez

Ahora, para que me retorne los acentos completos lo que hago es convertir ese resultado con unicode():

unicode(nombre_completo('jperez',"utf-8"))

De esa manera la funcion tiene un string con acentos, caso contrario en lugar de mostrar José muestra Josx\02e ( o algo por el estilo), entonces resolvi ese problema con el famoso "unicode"

mi problema esta en que necesito insertar esa informacion un una tabla de Microsoft SQL Server 2005, y para eso uso la libreria pymssql

Cuando "armo" el SQL a modo de string incluyendo mi variable con acentos python me da el error :

UnicodeDecodeError: 'ascii' codec can't decode byte 0xb4 in position 9: ordinal not in range(128)

Pero esto no es cuando "ejecuto" el SQL sino cuando estoy declarando la variable str que contiene el SQL Insert into.. a modo de texto, ya que luego de eso la idea es ejecutar la insercion en la base de datos.

En resumen, es un lio esto de los juegos de caracteres, alguien entiende algo sobre este asunto ?

Mil gracias de antemano por cualquier luz en este tunel.

Saludos

Nicolas Valcárcel

unread,
Jul 16, 2012, 1:22:48 PM7/16/12
to pytho...@googlegroups.com
Carlos, lo primero que debes hacer es "avisarle" a tu script que va a
correr en modo UTF-8 para esto, la primera linea de tu script debe
ser:
# -*- coding: UTF-8 -*-

prueba si solo ese cambio arregla tu problema.
En caso NO lo arregle, por demas no solo de arreglar esto sino por
seguridad trata de usar esto en vez de unicode:
variable = u'%s' % nombre_completo('jperez')
y cada vez que vayas a usar el texto trata de escaparlo de esa manera
a un unicode string, el cual se "declara" como
u'CONTENIDO_DE_TU_STRING_EN_UNICODE' y creara un objecto unicode sin
necesida de "codificarlo" cada vez.

2012/7/16 Carlos Herrera Polo <carlos.he...@gmail.com>:
> --
> Has recibido este mensaje porque estás suscrito al grupo "Python Perú" de
> Grupos de Google.
> Para publicar una entrada en este grupo, envía un correo electrónico a
> pytho...@googlegroups.com.
> Para anular tu suscripción a este grupo, envía un correo electrónico a
> python-peru...@googlegroups.com
> Para tener acceso a más opciones, visita el grupo en
> http://groups.google.com/group/python-peru?hl=es.



--
aka nxvl
Yo uso Software Libre, y tu?

Carlos Herrera Polo

unread,
Jul 16, 2012, 2:30:24 PM7/16/12
to pytho...@googlegroups.com
Gracias Nicolas por la respuesta.
Lamentablemente continua sin funcionar y el error se mantiene.

En mi script indique # -*- coding: UTF-8 -*- al principio
Luego, hice lo que me comentase de convertirlo a unicode pero el error es exactamente el mismo.
Probando un poco mas me doy cuenta que ya el texto "José" esta en unicode (o algo similar), hice lo siguiente:

cuenta = nombre_completo('jperez')

variable1 = cuenta
variable2 = u'%s' % cuenta

Print variable1
Print variable2

En ambos casos siempre me retorna "José Perez".
Asumo entonces que ya la funcion esta retornando en unicode,  lo confirmo puesto que antes de retornar el resultado la funcion hace:

nombre_latin = unicode(nombre,"utf-8")

return nombre_latin

Entonces... el problema es al armar el string

Es posible que cuando estoy concatenando el "string" con varias variables, una de ellas este en unicode y otra en otro "formato" y cuando se "unen" para formar el unico str de SQL ahi surge el problema ?

Gracias nuevamente

Nicolas Valcárcel

unread,
Jul 16, 2012, 2:52:55 PM7/16/12
to pytho...@googlegroups.com
La suma de unicode + string es unicode:
In [1]: foo = u'José'

In [2]: bar = 'Perez'

In [3]: meow = foo + bar

In [4]: type(meow)
Out[4]: unicode

In [5]: type(bar)
Out[5]: str

incluso al escapar un unicode a un string lo convierte a string:
In [6]: cow = "%s" % foo

In [7]: print cow
José

In [8]: type(cow)
Out[8]: unicode

Puedes poner un poco mas del traceback para ver donde exactamente es
que se esta quejando del unicode?

Nicolas Valcárcel

unread,
Jul 16, 2012, 2:53:36 PM7/16/12
to pytho...@googlegroups.com
y el codigo de como "armas" tu SQL

2012/7/16 Nicolas Valcárcel <nvalc...@gmail.com>:

Carlos Herrera Polo

unread,
Jul 16, 2012, 2:58:46 PM7/16/12
to pytho...@googlegroups.com
Claro nicolas, aca te envio parte del cofigo


    # INSERTA EN LA CABECERA

    print '1',nombre_completo
    abogado = u'%s'%nombre_completo
    print '2',nombre_completo
   
    print '3', notas
    notas = u'%s' % notas
    print '4', notas

    sql_insert_cabecera = """
    INSERT INTO Documento_2 (idDocumento, Nombre, Extensiondocumento, idTipoDocumento, titulo, asunto, keywords, autores, rutaDocumento, folderpath, Estado) VALUES (%d,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')
    """ % (fila_excel - 1, nombre , extension , '1',nombre, notas, '',nombre_completo, ruta_documental,ruta_documentos,'')



Antes de poner esos "print" para ir depurando, se caia en la declaracion de la variable "sql_insert_cabecera", luego que puse los print se cae cuando hace notas = u'%s' % notas

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd3 in position 5: ordinal
not in range(128)

Gracias

Jj

unread,
Jul 16, 2012, 3:00:19 PM7/16/12
to pytho...@googlegroups.com
Esto es ajeno al problema de unicode, pero por favor usen un ORM o al
menos quoting de los strings interpolados.
Jj
http://isgeek.net/
- Don't make me hate email: http://goo.gl/hk9q

Carlos Herrera Polo

unread,
Jul 16, 2012, 3:11:41 PM7/16/12
to pytho...@googlegroups.com
No comprendo el porque usar un ORM...
Es un script que estoy desarrollando para migracion de información de un sistema a otro, no mas de 300 lineas..

Nicolas Valcárcel

unread,
Jul 16, 2012, 3:33:57 PM7/16/12
to pytho...@googlegroups.com
Ok, antes de ese print pon un pdb
import pdb
pdb.set_trace()

y revisa que hay en notas.
seria bueno que le des un type(notas), lo imprimas, etc... para ver
que objecto te esta creando.

Lo que dice Jj es cierto, al final tu estas haciendo un ORM, o especie
de, usar uno que ya haya te ahorraria estos dolores de cabeza. pero si
es un script chiquito de un solo uso esta bien, probablemente.

Nicolas Valcárcel

unread,
Jul 16, 2012, 3:36:46 PM7/16/12
to pytho...@googlegroups.com
y a todo esto, intenta olvidarte que print acepta comas. mejor usa
esto, es mas ordenado:

print '1 %s' % nombre_completo
abogado = u'%s'%nombre_completo
print '2 %s' % nombre_completo

print '3 %s' % notas
notas = u'%s' % notas
print '4' %s % notas

cuando construya strings SIEMPRE trata de usar esto, te va a ahorrar
algunos problemas de seguridad y hacer mas notorios problemas como el
que estas teniendo, lease, si tu linea donde creas el
sql_insert_cabecera no la hubieras construido asi probablemente
hubieras roto la base de datos de alguna manera.

2012/7/16 Nicolas Valcárcel <nvalc...@gmail.com>:

Ider Delzo

unread,
Jul 16, 2012, 3:46:15 PM7/16/12
to python-peru
Creo que seria mas productivo si mandas el traceback del error que
sale, nos ahorrariamos mucho tiempo, puede que el error no sea en tu
codigo sino en la libreria que utilizas o algo por el esstilo.

Saludos.

Excerpts from Nicolas Valcárcel's message of Mon Jul 16 14:36:46 -0500 2012:

Mario Rodas

unread,
Jul 16, 2012, 3:54:13 PM7/16/12
to pytho...@googlegroups.com
Hola:

>>> cuenta = 'José Perez'
>>> nombre, apellido = map(lambda s: s.decode('utf-8'), cuenta.split(' '))
>>> nombre
u'Jos\xe9'
>>> apellido
u'Perez'
>>>

http://nedbatchelder.com/text/unipain.html

Saludos
...
Mario Rodas

Carlos Herrera Polo

unread,
Jul 16, 2012, 4:07:08 PM7/16/12
to pytho...@googlegroups.com

Las variables (Abogado y notas) ambas son de tipo "unicode", acabo de revisarlo.

La variable notas contiene lo siguiente:
"VERSIËN EN PDF DEL INFORME"

Cuando intento pasarla a unicode

notas = u'%s'%notas

Me arroja el mensaje :

notas = u'%s'%notas

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd3 in position 5: ordinal not in range(128)



Mario Rodas

unread,
Jul 16, 2012, 4:17:13 PM7/16/12
to pytho...@googlegroups.com
Hola:

Te estñá diciendo que no puede decodear "notas" a ascii.

>>> notas = "VERSIËN EN PDF DEL INFORME"
>>> notas.decode('utf-8')
u'VERSI\xcbN EN PDF DEL INFORME'

Debes usar .encode() y .decode()

Saludos
...
Mario Rodas

Carlos Herrera Polo

unread,
Jul 16, 2012, 4:23:16 PM7/16/12
to pytho...@googlegroups.com
Gracias Mario..
Algo debo estar haciendo mal

Hice lo que me sugeriste:
Pero cuando ejecuta la linea donde hago el "decode" me da el mensaje:


notas = "VERSIËN EN PDF DEL INFORME"
Traceback (most recent call last):
  File "C:\scripts\DMS_DOCUMENTAL_TO_DCMT.py", line 279, in <module>
    notas = notas.decode('utf-8')
  File "C:\Python26\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 5-6: invalid data

Imagino que se debe al caracter Ë , el cual debe ser Ó .. .algo esta haciendo ese caracter con mi cadena :S


Mariano Reingart

unread,
Jul 16, 2012, 5:07:57 PM7/16/12
to pytho...@googlegroups.com
Hola, yo uso pyodbc, y para manejar unicode correctamente, me ayudo
pasarle los siguientes parámetros {'CHARSET': 'LATIN1', 'ANSI': True,
'unicode_results': True}
Luego debés pasar las consultas como unicode (con la u).

Pido disculpas si ya lo habian comentado antes, no pude seguir todo el thread.

Espero que les sirva,

Sds

Mariano Reingart
http://www.sistemasagiles.com.ar
http://reingart.blogspot.com




2012/7/16 Carlos Herrera Polo <carlos.he...@gmail.com>:

Carlos Herrera Polo

unread,
Jul 16, 2012, 7:19:04 PM7/16/12
to pytho...@googlegroups.com
Gracias Mariano por la sugerencia.
Aunque veo que el problema no es en la libreria de conexion con la BD sino antes, cuando declaro una variable...

Martín Félix Muñoz del Río

unread,
Jul 16, 2012, 7:03:32 PM7/16/12
to pytho...@googlegroups.com
Hola,

Puedes probar con: notas.decode('utf-8','replace')

Revisa: http://wiki.python.org/moin/UnicodeDecodeError

Saludos
--
Ing. Martín Félix Muñoz del Río
CIP: 56927L
Nuestros servicios: http://www.simuder.com

Carlos Herrera Polo

unread,
Jul 16, 2012, 7:55:21 PM7/16/12
to pytho...@googlegroups.com
A ver.. antes que nada gracias a todos por el interes y apoyo.
Les cuento que paso

Lo que he encontrado y entiendo es lo siguiente:

La funcion nombre_completo YA retorna un tipo de dato unicode, por esta razon puede retornar sin problemas : "José Perez"

Esa variable es "unicode" definitivamente.

Mi problema esta cuando intento armar mi variable "sql" que es una de tipo string.
Para poder hacer esto he descubierto gracias a ustedes que antes de "armar" el SQL debo convertir esa variable a "ascii" (string), de esta forma:

nombre_usuario = nombre_usuario.encode('ascii', 'replace')

o tambien

nombre_usuario = nombre_usuario.encode('ascii', 'ignore')

De esta forma la declaracion de la variable "sql" no da errores. Pero ahora he descubierto que cuando esta guardando datos en la tabla no guarda acentos y escribe en mssql server:

Jos? Perez
ó
Jos Perez

Dependiendo si use "ignore" o si use "reglace"

Ahora mi problema se enfoca a como guardar datos con acentos en MSSQL Server sin este problema...

Lo que me es raro es lo siguiente:

Si recupero un registro en SQL del tipo de dato "char" y la data tiene acento y luego con un cursor recupero el valor en una variable python para luego esa misma subirla en otra tabla/columna con un sql "armado" utilizando mi variable que contiene la tilde, si graba en la base de datos con tilde... ahora,no tiendo el porque de otra manera no guarda acentos.

Me he quedado mas confundido que le chino japones que invento la confusion...

Nicolas Valcárcel

unread,
Jul 16, 2012, 8:07:40 PM7/16/12
to pytho...@googlegroups.com
Eso esta en la configuracion y codificacion de tu base de datos, trata
de hacer un query a mano insertando una palabra con acentos, si falla,
no tiene nada que ver con python. Si puedes hacerlo, revisa que datos
esta mandado exactamente (imprime el sql antes de mandarlo?)

2012/7/16 Carlos Herrera Polo <carlos.he...@gmail.com>:

Martín Félix Muñoz del Río

unread,
Jul 16, 2012, 8:23:47 PM7/16/12
to pytho...@googlegroups.com
Hola,

El 16 de julio de 2012 18:55, Carlos Herrera Polo <carlos.he...@gmail.com> escribió:
A ver.. antes que nada gracias a todos por el interes y apoyo.
Les cuento que paso

Lo que he encontrado y entiendo es lo siguiente:

La funcion nombre_completo YA retorna un tipo de dato unicode, por esta razon puede retornar sin problemas : "José Perez"

Esa variable es "unicode" definitivamente.

Mi problema esta cuando intento armar mi variable "sql" que es una de tipo string.
Para poder hacer esto he descubierto gracias a ustedes que antes de "armar" el SQL debo convertir esa variable a "ascii" (string), de esta forma:

nombre_usuario = nombre_usuario.encode('ascii', 'replace')
¿no deberías usar?

nombre_usuario = nombre_usuario.encode('utf-8')
 

per...@gmail.com

unread,
Jul 17, 2012, 12:58:29 AM7/17/12
to pytho...@googlegroups.com
El unicode tiene distintos encodings, entre los mas usados estan el ascii y el latin-1.

Lamentablemente el "default" conversion de python de latin-1 a ascii encoding , no hace ni replace ni ignore, sino bota una excepcion cuando encuentra un caracter que no se puede guardar en ascii.

Esta conversion a encoding ascii, se debe estar dando ya sea x la configuracion de tu base de datos, o mas probablemente x la configuracion o soporte de encodings de la libreria que estas usando para conectarte a tu bd.
Que libreria estas usando x ello y que base de datos estas usando ?

Saludos,
Rafael
Sent from my BlackBerry® smartphone

From: Martín Félix Muñoz del Río <marti...@gmail.com>
Date: Mon, 16 Jul 2012 19:23:47 -0500
Subject: Re: [python-peru] Acentos , python y pymssql

Rafael Olaechea

unread,
Jul 17, 2012, 1:09:33 AM7/17/12
to pytho...@googlegroups.com
Y no martin, nombre_usuario = nombre_usuario.encode('utf-8') no va ayudar. 

El problema es precisamente que su base de datos no esta en encoding sino probablemente en latín-1 o en ascii (los tres: utf-8, latín-1, y ascii son encodings validos de unicode).


2012/7/16 Martín Félix Muñoz del Río <marti...@gmail.com>

Carlos Herrera Polo

unread,
Jul 17, 2012, 10:36:54 AM7/17/12
to pytho...@googlegroups.com
Acabo de hacer un pequeño script de prueba sin incluir los algoritmos de base de datos, el problema no es de Base de datos sino algo mas sencillo,

El programita lo que hace es llamar a nombre_usuario() que retorna "José Pérez", como un tipo de dato "unicode" (ya lo comprobe depurando)
Luego, me doy cuenta que el tipo de dato c (Canción) es "str"
El problema esta cuando se esta concatenando los valores , me bota el error:

File "C:\scripts\prueba.py", line 46, in <module>
    """ % ( a , b , c)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf3 in position 5: ordinal
not in range(128)


Ahora, si hago c=u'Canción' la variable sql_insert_cabecera si toma los valores con acento sin problema, me parece que mi problema es cuando concateno variables de tipo str y unicode...

=============== PROGRAMA DE PRUEBA =================
# -*- coding: latin-1

a = 'jperez'
b = nombre_usuario(a)
c = 'Canción'

sql_insert_cabecera = """
    INSERT INTO Documento_2 ( Nombre1,Nombre2,tema) VALUES ('%s','%s','%s')
    """ % ( a , b , c)
====================================================

Carlos Herrera Polo

unread,
Jul 17, 2012, 10:54:55 AM7/17/12
to pytho...@googlegroups.com
POR FIN !!!
Resolvi el problema, era algo relativamente sencillo, el asunto esta con el famoso unicode.

Segui los pasos de este blog:

http://elviajedelnavegante.blogspot.com/2010/02/xml-y-python-unicode.html

Como por arte de magia, mi script dejo de fallar, bastaba con hacer esto (copio del blog)

Hay que crear un fichero, llamado sitecustomize.py. Este fichero puede estar en cualquier parte, siempre que el import pueda encontrarlo, pero normalmente se encuentra en el lib/site-packages de Python. Si por ejemplo se utiliza Python 2.5, este fichero debería de crearse en c:\Python25\Lib\site-packages.

El contenido sería el siguiente:

import sys
sys.setdefaultencoding('iso-8859-1')

Con eso se arreglo perfecto, y la base de datos veo que tiene los registros con acento.
Copio esto a la lista de correo por si a alguien le da el mismo problema sepa como solucionarlo, yo pase 3 dias metido en este asunto y ya tenia pesadillas con unicode y ascii.

Un abrazo y felices fiestas patrias

Rafael Olaechea

unread,
Jul 17, 2012, 10:55:32 AM7/17/12
to pytho...@googlegroups.com
Mira el siguiente ejemplo:

>>> a = 'jperez'
>>> b = u"josé Perez"
>>> c = 'Canción'
>>> b + c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 5: ordinal not in range(128)

En cambio  el siguiente código funciona:

>>> b = u"josé Perez"
>>> c = 'Canción'
>>> b + unicode(c, 'utf-8')
u'jos\xe9 PerezCanci\xf3n'
>>> print b + unicode(c, 'utf-8') 
josé PerezCanción


El problema es que canción es un string con acentos, y al intentar juntarlo con un unicode, python intenta convertirlo x defecto usandon el encoding ascii que no soporta accentos. c = 'Cancion', lo debes convertir a unicode usando en este caso el encoding utf-8 que es usado el python para las constantes.

Entonces la solución sería cambiar tu programa de prueba a  (ojo usa como encoding utf-8):

# -*- coding: utf-8                                                                                                                                                                                         

a = 'jperez'
b = u'Jose Pérez'
c = 'Canción'

sql_insert_cabecera = """                                                                                                                                                                                   
    INSERT INTO Documento_2 ( Nombre1,Nombre2,tema) VALUES ('%s','%s','%s')                                                                                                                                 
    """ % ( a , b , unicode(c, 'utf-8'))

print sql_insert_cabecera





2012/7/17 Carlos Herrera Polo <carlos.he...@gmail.com>

Carlos Herrera Polo

unread,
Jul 17, 2012, 10:58:29 AM7/17/12
to pytho...@googlegroups.com
Gracias Rafael, probare tambien de esa manera.
Aunque creo que la opcion que encontre en el blog es mas sencilla de utilizar.
De todas maneras voy a intentarlo.

Gracias a todos por su apoyo en este asunto.

Rocio Marquez

unread,
Jul 17, 2012, 11:00:28 AM7/17/12
to pytho...@googlegroups.com
y en el caso de crear un ejecutable..con py2exe...a mi genera error " UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 5: ordinal not in range(128) "..pero cuando lo compilo en mi IDLE de python no me genera ningun error...mi problema es cuando genero el ejecutable de dicho script..saben algo?

El 17 de julio de 2012 09:55, Rafael Olaechea <per...@gmail.com> escribió:

Mario Rodas

unread,
Jul 18, 2012, 1:16:57 AM7/18/12
to pytho...@googlegroups.com
Hola:

Rocio, ¿podrias abrir otro hilo añadiendo el traceback?

Saludos
...
Mario Rodas
Reply all
Reply to author
Forward
0 new messages