2012-07-31 13 views
5

pierwszy post więc proszę być uprzejmy, Przeszukałem wiele wokół, ale większość rzeczy znalazłem są istotne dla Pythona 2.Python3: UnicodeEncodeError tylko wtedy, gdy uruchomiony z crontab

Mam skrypt Python3 które buduje plik zip z lista plików; kończy się niepowodzeniem z UnicodeEncodeError tylko wtedy, gdy skrypt jest uruchamiany z crontab, ale działa bezbłędnie po uruchomieniu z interaktywnej konsoli. Chyba musi być coś w środowisku, ale po prostu nie mogę się dowiedzieć co.

Jest to fragment kodu:

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

I to jest wyjście log na ten fragment kodu:

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 

Jest to linia crontab:

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

I jest zawartość runbackup.sh:

#! /bin/bash -l 

cd /home/vte/vtebackup/vte41/scripts 

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

Plik na którym wyjątek dzieje jest zawsze taka sama, ale to nie wydaje się zawierać żadnych innych niż znaki ASCII:

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

OS Ubuntu LTS 10.04, Python w wersji 3.2 (zainstalowany z boku z boku jako altinstall z innymi wersjami Pythona). Wszystkie pliki źródłowe Pythona mają tę shebang

#!/usr/bin/env python3.2 

jako pierwszy linię

możesz mi pomóc znaleźć to, co się dzieje i jak rozwiązać ten problem?

+0

z nieznanego powodu, gdy zipfile dociera do kodowania pliku, aby umieścić w nim informacje, nazwa pliku ma [Unicode surogatu] (http://www.htmlescape.net/dc/unicode_char_dcc3 .html). Może problem z systemem operacyjnym? Czy możesz zapisać plik 'curfile' w swoim skrypcie? – CharlesB

Odpowiedz

11

Członek zespołu znalazł rozwiązanie w postaci Python bug thread.

Problem został rozwiązany przez poprzedzenie dyrektywę LANG do komendy skryptu:

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

Mam nadzieję, że jest to przydatne dla innych, ponieważ mam sobie zarysowania głowę na chwilę na to :)

+0

Nice found, thanks for sharing – CharlesB

+0

Dzięki temu uratowałem moje życie. – akai

4

Sprawdź swoją lokalizację. W konsoli interaktywnej uruchom komendę locale. Oto co mam:

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 określa jak interpretować nazwy plików na podstawie jednej zmiennej LC_CTYPE lub LANG środowiska, a ja mocno podejrzewać, że jeden z nich jest ustawiony w innym kodowaniu w środowisku cron.

Jeśli tak jest, twoje nazwy plików zostaną zdekodowane na kod Unicode za pomocą innego kodowania, które spowoduje nazwy plików, które nie mogą być zakodowane do UTF-8 lub ASCII.

Wystarczy ustawić zmienną LC_CTYPE w definicji cron, albo na linii na własną poprzedzającym wejście w czasie, lub jako część polecenia do wykonania:

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

Jak zawsze w kwestiach pyton Unicode w odpowiedź leży w Unicode HOWTO, section on filenames.

1

dla chińskich

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 
+0

'LC_ALL =" en_US.utf-8 "' działa dobrze 4 ja – Jim

Powiązane problemy