Pergunta

Eu uso o módulo zipfile de python para extrair um arquivo .zip (Vamos dar esse arquivo em http :?. //img.dafont.com/dl/ f = akvaleir por exemplo)

f = zipfile.ZipFile('akvaleir.zip', 'r')
for fileinfo in f.infolist():
    print fileinfo.filename
    f.extract(fileinfo, '.')

Sua saída:

Akval�ir_Normal_v2007.ttf
Akval�ir, La police - The Font - Fr - En.pdf

Ambos os arquivos estão unaccessable após a extração, porque há caracteres codificados inválidos em seus nomes. O problema é o módulo zipfile não tem uma opção para especificar nomes de arquivos de saída.

No entanto, "unzip akvaleir.zip" escapa o nome do arquivo bem:

root@host:~# unzip akvaleir.zip 
Archive:  akvaleir.zip
  inflating: AkvalВir_Normal_v2007.ttf  
  inflating: AkvalВir, La police - The Font - Fr - En.pdf  

Eu tentei capturar saída do "unzip -l akvaleir.zip" no meu programa python e estes dois nomes são:

Akval\xd0\x92ir_Normal_v2007.ttf
Akval\xd0\x92ir, La police - The Font - Fr - En.pdf

Como posso obter o nome do arquivo correto como o comando unzip faz sem capturar saída do "unzip -l akvaleir.zip"?

Foi útil?

Solução

Em vez do método extract, utilize o método open e salvar o pseudofile resultando no disco com o nome que você quiser, por exemplo, com shutil.copyfileobj .

Outras dicas

Levou algum tempo, mas eu acho que encontrei a resposta.

Eu assumi a palavra deveria ser Akvaléir. Eu encontrei uma descrição da página sobre isso, em francês. Quando eu usei o trecho de código que eu tinha uma string como

>>> fileinfo.filename
'Akval\x82ir, La police - The Font - Fr - En.pdf'
>>> 

Isso não funcionou em UTF8, Latin-1, CP-1251 ou CP-1252 codificações. Eu, então, descobriu que CP863 foi uma possível codificação canadense, talvez isso foi do francês no Canadá.

>>> print unicode(fileinfo.filename, "cp863").encode("utf8")
Akvaléir, La police - The Font - Fr - En.pdf
>>> 

No entanto, eu então leia o formato de arquivo Zip especificação que diz

O formato ZIP tem historicamente suportado apenas o original IBM PC codificação de caracteres conjunto, comumente referido como Código IBM página 437.

...

Se propósito geral bit 11 é definido, o filename e comentários devem suportar o Padrão Unicode, Versão 4.1.0 ou maior usando a codificação de caracteres forma definida pelo armazenamento UTF-8 especificação.

Testing isso me dá a mesma resposta que a página de código canadense

>>> print unicode(fileinfo.filename, "cp437").encode("utf8")
Akvaléir, La police - The Font - Fr - En.pdf
>>>

Eu não tenho um Unicode codificado zip arquivo e eu não estou indo para criar um para descobrir, então eu vou assumir que todos os arquivos zip tem a codificação CP437.

import shutil
import zipfile

f = zipfile.ZipFile('akvaleir.zip', 'r')
for fileinfo in f.infolist():
    filename = unicode(fileinfo.filename, "cp437")
    outputfile = open(filename, "wb")
    shutil.copyfileobj(f.open(fileinfo.filename), outputfile)

No meu Mac que dá

 109936 Nov 27 01:46 Akvale??ir_Normal_v2007.ttf
  25244 Nov 27 01:46 Akvale??ir, La police - The Font - Fr - En.pdf

que guia-concluída a

ls Akvale\314\201ir

e aparece com um bom 'é' no meu navegador de arquivos.

Eu corri para um problema semelhante durante a execução meu aplicativo usando Docker. Adicionando estas linhas ao Dockerfile, tudo fixo para mim:

RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

Então, eu acho que se você não está usando Docker, experimentá-lo e certifique-se locais estão devidamente gerado e set.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top