У меня есть сценарий 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 из таблицы, содержащей умляут вроде ä, ö или ü, сценарий просто завершается. Я проверил это, записав вывод скрипта в файл.
Поэтому я протестировал сценарий, вызвав его вручную в оболочке, просто набрав «python myscript.py», и он отлично работает без каких-либо проблем.
Поэтому я предполагаю, что проблема на самом деле не в самом скрипте, а как-то в среде cron.
Надеюсь, кто-нибудь из вас сможет дать мне совет. Я совершенно запутался.
Любая помощь приветствуется.
---------------- Ответ на комментарий 1:
Спасибо за подсказку с локалью.
Сначала я написал "локаль" на стандартной оболочке. Это дало мне следующий результат:
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
Затем я отредактировал файл cron с помощью «crontab -e» и добавил следующую строку
*/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=
Итак, это может быть проблемой? Как я могу это исправить?
Вы декодируете строки в Unicode с помощью unicode(daten[i][j])
. Когда вы не указываете кодировку, Python использует системное значение по умолчанию, которое, вероятно, является ascii при запуске скрипта через cron.
В любом случае вы должны указать фактическую кодировку, используемую базой данных. Ты можешь использовать unicode(daten[i][j], dbencoding)
вместо этого или попросите адаптер базы данных напрямую выдавать вам Unicode.
Кстати: существует, вероятно, миллион инструментов, которые генерируют файлы cvs из запросов к базе данных, MySQL имеет это даже встроенное. Ваш код, с другой стороны, довольно хрупок, потому что вы вообще не можете убежать.
Хорошо, теперь я выяснил, в чем проблема. Это не имеет ничего общего с кодом, ну ладно, это уже было ясно раньше, но проблема в переменных локального языка.
В задании 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')
Но это не сработало.
Как мне это изменить?
Я почти уверен, что проблема в этом. MySQL рассмотрит настройки вашей локали, чтобы определить кодировку символов для возврата значений. Я также знаю, что латинские символы с умляутами при кодировании в ISO-8859-1 не являются допустимыми символами UTF-8, и любой декодер завершится ошибкой, если попытается декодировать их (и без установки локали ваш клиентский модуль db может использовать это по умолчанию). Я не пробовал и не знаю, какую версию python вы используете, но гуглил python locale
вернул эту ссылку: http://docs.python.org/library/locale.html Так. я бы попробовал
import locale
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')
в самом начале вашего скрипта перед импортом модуля подключения к базе данных и посмотрите, работает ли это.