2012-09-27 3 views
0

저는 Ubuntu 12 x64에서 Python 2.7.3을 사용하고 있습니다.파일 이름을 처리하는 중 UnicodeDecodeError

내 파일 시스템의 폴더에 약 200,000 개의 파일이 있습니다. 일부 파일의 파일 이름에는 파일이 원래 웹 사이트에서 다운로드 되었기 때문에 html로 인코딩되고 이스케이프 된 문자가 포함됩니다. 다음은 예입니다

Jamaica%2008%20114.jpg
thai_trip_%E8%B0%83%E6%95%B4%E5%A4%A7%E5%B0%8F%20RAY_5313.jpg

내가 폴더를 통과하고 파일 이름에 인코딩 된 문자로 모든 파일의 이름을 변경하는 간단한 파이썬 스크립트를 썼다. 새 파일 이름은 단순히 파일 이름을 구성하는 문자열을 디코딩하면됩니다.

스크립트는 파일의 대부분을 작동하지만, 파이썬이된다는 일부 파일에 대한 다음과 같은 오류 밖으로 뱉어 :

def cleanupString(string): 
    string = urllib2.unquote(string) 

    return HTMLParser.HTMLParser().unescape(string) 
:

여기
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 11: ordinal not in range(128) 
Traceback (most recent call last): 
    File "./download.py", line 53, in downloadGalleries 
    numDownloaded = downloadGallery(opener, galleryLink) 
    File "./download.py", line 75, in downloadGallery 
    filePathPrefix = getFilePath(content) 
    File "./download.py", line 90, in getFilePath 
    return cleanupString(match.group(1).strip()) + '/' + cleanupString(match.group(2).strip()) 
    File "/home/abc/XYZ/common.py", line 22, in cleanupString 
    return HTMLParser.HTMLParser().unescape(string) 
    File "/usr/lib/python2.7/HTMLParser.py", line 472, in unescape 
    return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", replaceEntities, s) 
    File "/usr/lib/python2.7/re.py", line 151, in sub 
    return _compile(pattern, flags).sub(repl, string, count) 

내 cleanupString 기능의 내용입니다

그리고 여기가 cleanupString 함수를 호출하는 코드의 조각입니다 (이 코드는 위의 추적에서 동일한 코드는 아니지만 같은 오류 발생) :

rootFolder = sys.argv[1] 
pattern = r'.*\.jpg\s*$|.*\.jpeg\s*$' 
reobj = re.compile(pattern, re.IGNORECASE) 
imgs = [] 

for root, dirs, files in os.walk(rootFolder): 
    for filename in files: 
     foundFile = os.path.join(root, filename) 

     if reobj.match(foundFile): 
      imgs.append(foundFile) 

for img in imgs : 
    print 'Checking file: ' + img 
    newImg = cleanupString(img) #Code blows up here for some files 

누구든지이 오류를 해결할 수있는 방법을 제공 할 수 있습니까? 이미 추가를 시도했습니다.

# -*- coding: utf-8 -*- 

스크립트 상단에 추가했지만 아무 효과가 없습니다.

감사합니다.

답변

6

파일 이름은 유니 코드 문자를 나타내는 UTF-8 바이트를 포함하는 바이트 문자열입니다. HTML 파서는 일반적으로 바이트 문자열 대신 유니 코드 데이터와 함께 작동합니다. 특히 앰퍼샌드 이스케이프가 발생할 때 파이썬이 자동으로 값을 디코딩하려고하지만 기본적으로 디코딩에 ASCII을 사용합니다. UTF-8 데이터에는 ASCII 범위를 벗어나는 바이트가 포함되어 있으므로이 작업은 실패합니다.

당신은 명시 적으로 유니 코드 객체에 문자열을 디코딩해야합니다

def cleanupString(string): 
    string = urllib2.unquote(string).decode('utf8') 

    return HTMLParser.HTMLParser().unescape(string) 

당신의 다음 문제는 이제 유니 코드 파일 이름을 가지고있을 것이다, 그러나 당신의 파일 시스템이 파일 이름과 함께 작동하도록 인코딩의 일종이 필요합니다. 해당 인코딩이 무엇인지 확인할 수 있습니다 sys.getfilesystemencoding(); 당신의 파일 이름을 다시 인코딩이 사용

def cleanupString(string): 
    string = urllib2.unquote(string).decode('utf8') 

    return HTMLParser.HTMLParser().unescape(string).encode(sys.getfilesystemencoding()) 

당신은 Unicode HOWTO에서 유니 코드와 어떻게 파이썬 거래에 읽을 수 있습니다.

+0

Linux에서 파일 이름으로 작업 할 때는주의해야합니다. 설정된 문자 인코딩은 사용되지 않으며 명시 적으로 구성된 경우 (일반적으로 UTF-8)에도 그대로 따르지 않는 파일 이름을 얻을 수 있습니다. 일반적으로 말하는 원시 바이트 문자열로 처리해야하며, 유효하지 않은 이름이 있으면 최소한 넘어지지 않습니다. – spencercw

+0

생각해 보니 그의 인코딩 된 파일 이름이 반드시 UTF-8이 아니기 때문에 재미있을 수도 있습니다. – spencercw

+0

@spencercw : 그가 준 예는 다음과 같습니다. 그의 오류 메시지에있는'\ xe2' 바이트는 또 다른 단서이며, 전형적인 UTF-8 대리입니다. –

0

this issue에 부딪 치는 것 같습니다. unescapeunquote이라고하는 순서를 반대로 시도해 봅니다. unquote은 파일 이름에 비 ASCII 문자를 추가 할 것이므로 문제를 해결하지 못할 수도 있습니다.

실제로 질식하는 파일 이름은 무엇입니까?

+0

실제로 생각해 보면, 이것은 아마도 근본적인 문제이므로 올바른 답을 얻게됩니다 *. 그냥 내 것처럼 완전하지 않아. :-) –

+0

@spencercw : 여기 스크립트가 질식하는 파일 이름이 있습니다./ 갤러리/nath & a heartsofl ♥ ve/♥♥♥ pink ♥♥♥/DSC_0080.JPG –

+0

@spencercw : 당신이 제안한 것을 시도했지만 효과가 없으며 같은 오류가 발생했습니다. –

관련 문제