Python3: UnicodeEncodeError только при запуске из crontab

первый пост, так что будьте любезны, я много искал, но большинство вещей, которые я нашел, имеют отношение к Python 2.

У меня есть скрипт Python3, который создает zip-файл из списка файлов; сбой с UnicodeEncodeError только при запуске скрипта из crontab, но он работает безупречно при запуске из интерактивной консоли. Я предполагаю, что должно быть что-то в окружающей среде, но я просто не могу понять, что.

Это фрагмент кода:

def zipFileList(self, rootfolder, filelist, zip_file, logger):
    count = 0

    logger.info("Generazione file zip {0}: da {1} files".format(zip_file, len(filelist)))
    zip = zipfile.ZipFile(zip_file, "w", compression=zipfile.ZIP_DEFLATED)

    for curfile in filelist:
        zip.write(os.path.join(rootfolder, curfile), curfile, zipfile.ZIP_DEFLATED)
        count = count + 1

    zip.close()
    logger.info("Scrittura terminata: {0} files".format(count))

И это вывод журнала для этого фрагмента кода:

2012-07-31 09:10:03,033: root - ERROR - Traceback (most recent call last):
  File "/usr/local/lib/python3.2/zipfile.py", line 365, in _encodeFilenameFlags
  return self.filename.encode('ascii'), self.flag_bits
UnicodeEncodeError: 'ascii' codec can't encode characters in position 56-57: ordinal not in range(128)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "XBE.py", line 45, in main
    pam.executeList(logger)
  File "/home/vte/vtebackup/vte41/scripts/ptActivityManager.py", line 62, in executeList
    self.executeActivity(act, logger)
  File "/home/vte/vtebackup/vte41/scripts/ptActivityManager.py", line 71, in executeActivity
    self.exAct_FileBackup(act, logger)
  File "/home/vte/vtebackup/vte41/scripts/ptActivityManager.py", line 112, in exAct_FileBackup
    ptfs.zipFileList(srcfolder, filelist, arcfilename, logger)
  File "/home/vte/vtebackup/vte41/scripts/ptFileManager.py", line 143, in zipFileList
    zip.write(os.path.join(rootfolder, curfile), curfile, zipfile.ZIP_DEFLATED)
  File "/usr/local/lib/python3.2/zipfile.py", line 1115, in write
    self.fp.write(zinfo.FileHeader())
  File "/usr/local/lib/python3.2/zipfile.py", line 355, in FileHeader
    filename, flag_bits = self._encodeFilenameFlags()
  File "/usr/local/lib/python3.2/zipfile.py", line 367, in _encodeFilenameFlags
    return self.filename.encode('utf-8'), self.flag_bits | 0x800
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 56: surrogates not allowed

Это строка кронтаба:

10 9 * * * /home/vte/vtebackup/vte41/scripts/runbackup.sh >/dev/null 2>&1

А это содержимое runbackup.sh:

#! /bin/bash -l

cd /home/vte/vtebackup/vte41/scripts

/usr/local/bin/python3.2 XBE.py

Файл, в котором происходит исключение, всегда один и тот же, но, похоже, он не содержит символов, отличных от ascii:

/var/vhosts/vte41/http_docs/vtecrm41/storage/2012/July/week4/169933_Puccini_Gabriele.tif

ОС — Ubuntu Linux LTS 10.04, Python версии 3.2 (устанавливается вместе с другими версиями Python как альтернативная установка). Все исходные файлы Python имеют этот шебанг

#!/usr/bin/env python3.2

как самая первая строка

Можете ли вы помочь мне найти, что не так и как решить эту проблему?


person mabian69    schedule 31.07.2012    source источник
comment
По неизвестной причине, когда zipfile пытается закодировать имя файла для встраивания в него информации, имя файла содержит юникодный суррогат. . Может проблема в ОС? Можете ли вы зарегистрировать curfile в своем скрипте?   -  person CharlesB    schedule 31.07.2012


Ответы (3)


Член команды нашел решение проблемы в треде об ошибках Python.

Проблема была устранена путем добавления директивы LANG к команде скрипта:

* * * * * LANG=it_IT.UTF-8 /home/vte/vtebackup/vte41/scripts/runbackup.sh >/dev/null 2>&1

Я надеюсь, что это будет полезно для других, потому что я некоторое время почесал голову над этим :)

person mabian69    schedule 31.07.2012
comment
Спасибо, это спасло мне жизнь. - person akai; 08.03.2016
comment
В MacOS X import sys print(sys.getdefaultencoding()) задание cron показывает utf-8, но все же я получил упомянутую ошибку TS, и это решение решило мою проблему. - person sly; 31.08.2018

Проверьте свой регион. В интерактивной консоли выполните команду locale. Вот что я получаю:

LANG=
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL="en_US.UTF-8"

Python определяет, как интерпретировать имена файлов, основываясь на переменной среды LC_CTYPE или LANG, и я сильно подозреваю, что одна из них настроена на другую кодировку в вашей среде cron.

В этом случае ваши имена файлов будут декодированы в Unicode с использованием другой кодировки, которая затем приводит к именам файлов, которые не могут быть закодированы в UTF-8 или ASCII.

Просто установите переменную LC_CTYPE в вашем определении cron либо в отдельной строке, предшествующей записи времени, либо как часть выполняемой команды:

LC_CTYPE="en_US.UTF-8"
* * * * * yourscriptcommand.py

Как всегда в случае проблем с Unicode в Python, ответ содержится в разделе Unicode HOWTO, посвященном имена файлов.

person Martijn Pieters    schedule 31.07.2012

для китайского

export LANG="zh_CN.utf-8"                                                                            
export LC_CTYPE="zh_CN.utf-8"                                                                        
export PYTHONIOENCODING="utf-8"                                                                      

/export/zhangys/python3.5.2/bin/python3 diff_reporter.py > /home/admin/diff_script/cron_job.log 2>&1 
person lisency    schedule 14.10.2016