我有一个 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')
但那没有用。
我该如何改变这一点?