Python 编码问题

Python 编码问题

我有一个 Python 脚本,可以将数据从 mysql utf-8 表导出到文本文件。以下是执行该任务的代码

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();

我也尝试过

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

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

现在我不明白的部分是:

通常,此脚本应由 cron 作业调用。但是,当我从包含 ä、ö 或 ü 等变音符号的表中读取 varchar 时,脚本会终止。我通过将脚本的输出传输到文件中来检查这一点。

因此,我通过在 shell 上手动输入“python myscript.py”来测试该脚本,并且它运行正常,没有任何问题。

所以我的猜测是问题实际上并不在于脚本本身,而在于 cron 环境。

希望你们能给我一些建议。我完全糊涂了。

任何帮助都将受到赞赏。

---------------- 回答评论1:

谢谢您对语言环境的提示。

首先我在标准 shell 上输入了“locale”。它给出了以下输出:

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

然后我用“crontab -e”编辑了 cron 文件并添加了以下行

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

这个 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=

那么,这可能是问题所在?我该如何解决?

答案1

使用 将行解码为unicode unicode(daten[i][j])。如果您未指定编码,则Python将使用系统默认值,当您通过cron运行脚本时,该默认值可能是ascii。

无论哪种方式,您都必须提供数据库使用的实际编码。您可以改用unicode(daten[i][j], dbencoding),或者让数据库适配器直接为您提供 unicode。

顺便说一句:可能有上百万种工具可以通过数据库查询生成 cvs 文件,MySQL 甚至内置了此功能。另一方面,您的代码相当脆弱,因为您根本没有进行任何转义。

答案2

我非常确定这就是问题所在。MySQL 将查看您的语言环境设置以确定要返回值的字符编码。我还知道,在 ISO-8859-1 中编码时带有变音符号的拉丁字符不是有效的 UTF-8 字符,任何解码器在尝试解码它们时都会失败(如果没有设置语言环境,您的数据库客户端模块可能会默认为该设置)。我还没有尝试过,也不知道您使用的是哪个版本的 Python,但谷歌搜索python locale返回了此链接:http://docs.python.org/library/locale.html 所以,我会尝试

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

在剧本的开头在导入数据库连接模块之前看看是否有效。

答案3

好的,我现在知道问题是什么了。这与代码无关,好吧,之前已经很清楚了,但问题出在本地语言变量上。

在 cron 作业中,编码设置为 POSIX,而在正常 SHELL 模式下,编码设置为 UTF-8。因此,我将编码全部从 UTF-8 更改为 POSIX,然后运行我的脚本。令人惊讶的是,出现了与 cron 环境中相同的错误。因此,我现在一步一步地更改编码,我的意思是逐个变量地更改编码,然后检查我的脚本是否运行。

首先我改变了

导出 LANG=de_DE.UTF-8

运行脚本时仍然出现同样的错误。之后我更改了

导出 LC_CTYPE="de_DE.UTF-8"

然后脚本就运行得很好了。没有问题。

这就是问题所在。现在我该如何在我的 cron 环境中更改此变量?我已经在代码中尝试过了

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

但那没有用。

我该如何改变这一点?

相关内容