segunda-feira, 18 de maio de 2015

'ascii' codec can't decode byte


Por uma semana lutei contra esse erro procurando em muitos sites e fóruns uma solução. O que me ocorrei era que eu lia a partir de um zip os dados a serem inseridos em uma tabela, e o nome da tabela era retirado a partir do nome do arquivo em questão.

Para entender todo o cenário, vou tentar explicar usando meus os códigos:

def populateTable(data, tableName):
try:
lines = data.splitlines()

part1 = "insert into %s (" % tableName

for line in lines:
lineFields = ""
lineValues = ""

if len(line) == 0:
continue
elif len(line.strip()) == 0:
continue

for it1, it2 in self.table.iteritems():
lineFields += it1 + ","

if it2["tipo"] == "int":
lineValues += line[int(it2["inicio"])-1:int(it2["fim"])] + ","
else:
lineValues += "\"" + line[int(it2["inicio"])-1:int(it2["fim"])] + "\","

query = "insert into %s (%s) values (%s);" % (tableName, lineFields[:-1].lower(), lineValues[:-1])
self.executeQuery(query)

except ValueError as error:
raise

zf = zipfile.ZipFile(self.zipFile) # carrega o arquivo zip com todos os txts que precisarei ler e inserir no mysql

for filename in zf.namelist():
        dataToInsert = zf.read(filename)
        populateTable(dataToInsert, filename[:-4]) # retiro o .txt para sobrar apenas o que será o nome da tabela


Quando eu tentava concatenar o nome tabela (tableName) com os dados retirados desse arquivo, o python me dava o seguinte erro:

__main__:run.py:185 'ascii' codec can't decode byte 0xea in position 35: ordinal not in range(128)
Traceback (most recent call last):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 35: ordinal not in range(128)

Quando eu tentava concatenar o nome do arquivo com os dados retirados desse arquivo, o python me dava o seguinte erro:

__main__:run.py:185 'ascii' codec can't decode byte 0xea in position 35: ordinal not in range(128)
Traceback (most recent call last):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 35: ordinal not in range(128)


Após várias pesquisas, encontrei o erro, usando o seguinte teste. Procurei saber quais os tipos de objetos cada variável pertencia.

print type(tableName), repr(tableName)
<type 'unicode'> u' ... '

print type(lineValues), repr(lineValues)
<type 'str'> ' ... '

Assim, vi que a variável 'tableName' era do tipo 'unicode', e a 'lineValues' era do tipo 'str'. O problema era na hora de concatenar as duas variáveis. 

Para resolver foi simples, apenas fiz um cast para string na variável 'tableName' e tudo deu certo!

query = "insert into %s (%s) values (%s);" % (str(tableName), lineFields[:-1].lower(), lineValues[:-1])

Nenhum comentário:

Postar um comentário