Problema de codificação em Python

2

Eu tenho um script python que exporta dados de uma tabela mysql utf-8 para um arquivo de texto. Aqui está o código que faz o trabalho

csvDatei = codecs.open( csvDateiName, "w", "utf-8" )
...
cursor = db.cursor();
sql = "select * from %s.%s;" % (dbAusgang, tabelle)
cursor.execute(sql);
...
daten = cursor.fetchall();
for i in xrange(len(daten)):
    line = '';
    for j in xrange(len(daten[i])):
        line += '"%s";' % unicode(daten[i][j]);
    line = line[:-1];
    line += '\n';
    csvDatei.write(line);
csvDatei.close();

Eu também tentei isso

line += '"%s";' % str(daten[i][j]);

e

line += '"%s";' % daten[i][j];

E agora a parte que eu não entendo:

Normalmente, esse script deve ser chamado por uma tarefa cron. Mas quando eu leio um varchar de uma tabela que contém um trema como ä, ö ou ü o script simplesmente termina. Eu verifiquei isso canalizando a saída do script em um arquivo.

Por isso testei o script invocando-o manualmente no shell simplesmente digitando "python myscript.py" e ele corre perfeitamente bem sem problemas.

Então, meu palpite é que o problema realmente não está no script em si, mas sim no ambiente do cron de alguma forma.

Espero que qualquer um de vocês possa me dar conselhos. Estou completamente confuso.

Qualquer ajuda é apreciada.

---------------- Resposta para comentar 1:

Obrigado pela dica com a localidade.

Primeiro escrevi "locale" no shell padrão. Isso me deu a seguinte saída:

dhl@srv1093:~$ locale
LANG=de_DE.UTF-8
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES="de_DE.UTF-8"
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=de_DE.UTF-8

Depois editei o arquivo cron com "crontab -e" e adicionei a seguinte linha

*/1 * * * * locale > /home/user/locale.ouput

A saída deste cronjob é:

dhl@srv1093:~$ cat locale.ouput 
LANG=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

Então, isso pode ser o problema? Como posso consertar isso?

    
por TessellatingHeckler 11.06.2011 / 21:23

3 respostas

1

Você decodifica as linhas para unicode com unicode(daten[i][j]) . Quando você não dá nenhuma codificação, o Python usa o padrão do sistema, que é provavelmente ascii quando você executa o script através do cron.

De qualquer forma, você deve fornecer a codificação real usada pelo banco de dados. Você pode usar unicode(daten[i][j], dbencoding) ou obter seu adaptador de banco de dados para fornecer unicode diretamente.

Btw: Existem provavelmente um milhão de ferramentas que geram arquivos cvs a partir de consultas ao banco de dados, o MySQL tem isso mesmo embutido. Seu código, por outro lado, é bastante frágil porque você não tem como escapar.

    
por 11.06.2011 / 22:07
0

Tenho certeza de que esse é o problema. O MySQL examinará suas configurações de local para determinar a codificação de caracteres para retornar valores. Também sei que os caracteres latinos com umlauts quando codificados em ISO-8859-1 não são caracteres UTF-8 válidos e qualquer decodificador falhará se tentar decodificar eles (e sem um código de idioma, configure seu módulo cliente db como padrão). Eu não tentei e não sei qual versão do Python você está usando, mas googling python locale retornou este link: link Assim. Eu tentaria

import locale
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')

no início do seu script antes de importar seu módulo de conectividade do db e ver se isso funciona.

    
por 11.06.2011 / 23:23
0

Ok, agora descobri qual é o problema. Não tem nada a ver com o código, bem, tudo bem que já estava claro antes, mas as variáveis do idioma local são o problema.

No cron job as codificações são definidas para POSIX e no modo SHELL normal as codificações são definidas para UTF-8. Então eu mudei todas as codificações de UTF-8 para POSIX e executei meu script. E surpresa, o mesmo erro ocorre como no ambiente cron. Então agora eu mudo a codificação passo a passo, quero dizer variável por variável e verifico se meu script é executado ou não.

Primeiro eu mudei

export LANG = de_DE.UTF-8

e executando o script o mesmo erro permaneceu. Então depois disso mudei

export LC_CTYPE="de_DE.UTF-8"

e depois o script funcionou perfeitamente bem. Sem problemas.

Então esse é o problema. Agora, como eu mudo essa variável no meu ambiente cron? Eu já tentei no código

locale.setlocale(locale.LC_CTYPE, 'de_DE.UTF-8')

Mas isso não funcionou.

Como eu mudo isso?

    
por 12.06.2011 / 10:10