2009-01-30 10 views
13

J'écris un script qui doit déplacer un fichier, mais malheureusement, il ne semble pas os.path joue très bien avec l'internationalisation. Quand j'ai des fichiers nommés en hébreu, il y a des problèmes. Voici une capture d'écran du contenu d'un répertoire:os.path de Python étouffement sur les noms de fichiers hébreux

alt text http://eli.thegreenplace.net/files/temp/hebfilenameshot.png

considèrent maintenant ce code qui va sur les fichiers dans ce répertoire:

files = os.listdir('test_source') 

for f in files: 
    pf = os.path.join('test_source', f) 
    print pf, os.path.exists(pf) 

La sortie est:

test_source\ex True 
test_source\joe True 
test_source\mie.txt True 
test_source\__()'''.txt True 
test_source\????.txt False 

Notez comment os.path.exists pense que le fichier nommé hébreu n'existe même pas? Comment puis-je résoudre ce problème?

ActivePython sous Windows XP 2.5.2 SP2 Accueil

Répondre

15

Hmm, après some digging il apparaît que lors de l'alimentation os.listdir une chaîne unicode, cela fonctionne un peu:

files = os.listdir(u'test_source') 

for f in files: 

    pf = os.path.join(u'test_source', f) 
    print pf.encode('ascii', 'replace'), os.path.exists(pf) 

===>

test_source\ex True 
test_source\joe True 
test_source\mie.txt True 
test_source\__()'''.txt True 
test_source\????.txt True 

Quelques observations importantes ici:

  • Windows XP (comme tous les dérivés NT) stocke tous les noms de fichiers en unicode
  • os.listdir (et des fonctions similaires, comme os.walk) shoul d être passé une chaîne unicode afin de fonctionner correctement avec les chemins unicode. Voici une citation du lien ci-dessus:

os.listdir(), qui retourne les noms de fichiers, soulève une question: doit-il retourner la version Unicode de noms de fichiers, ou devrait-il retourner des chaînes 8 bits contenant les versions codées? os.listdir() fera les deux, selon si vous avez fourni le chemin du répertoire comme une chaîne 8 bits ou une chaîne Unicode . Si vous passez une chaîne Unicode comme le chemin, les noms de fichiers seront décodés en utilisant l'encodage et une liste des chaînes Unicode du système de fichiers sera retourné, en passant un chemin 8 bits retournera les versions 8 bits du noms de fichiers.

  • Enfin, print veut une chaîne ascii, non unicode, de sorte que le chemin doit être codé à ascii.
+0

impression ne semble pas être pointilleux sur ascii sur tous les environnements cependant. Vois ma réponse. – PEZ

+0

impression n'a pas de problème dans unicode d'impression: le problème peut être dans le codage stdout. Si la console est unicode, il n'y a pas de problème, sinon un encodage explicite est requis. – piro

+0

C'est excellent. Cela devrait signifier que vous pouvez rapporter des noms de fichiers sains sur Windows si vous imprimez sur un handle de fichier avec le bon encodage. Le gestionnaire d'erreur 'replace' me signale simplement la défaite. =) – PEZ

3

Il ressemble à un Unicode vs problème ASCII - os.listdir renvoie une liste de chaînes ASCII. Edit: Je l'ai essayé sur Python 3.0, également sur XP SP2, et os.listdir simplement omis les noms de fichiers hébraïques au lieu de les énumérer du tout.

Selon les documents, cela signifie qu'il a été incapable de le décoder:

Notez que lorsque os.listdir() retourne une liste de chaînes , les noms de fichiers qui ne peuvent pas être décodés correctement sont omis plutôt que de lever UnicodeError.

+0

Je suppose que je pourrais essayer, mais cela ne me aider comme je ne peux pas passer à 3,0 pour le moment. Je suis sûr qu'il devrait y avoir une solution pour 2,5 –

1

Il fonctionne comme un charme en utilisant Python 2.5.1 sur Mac OS X:

subdir/bar.txt True 
subdir/foo.txt True 
subdir/עִבְרִית.txt True 

Peut-être cela signifie que cela a à voir avec Windows XP en quelque sorte?

EDIT: J'ai aussi essayé avec des chaînes unicode pour essayer d'imiter le comportement de Windows mieux:

for f in os.listdir(u'subdir'): 
    pf = os.path.join(u'subdir', f) 
    print pf, os.path.exists(pf) 

subdir/bar.txt True 
subdir/foo.txt True 
subdir/עִבְרִית.txt True 

dans le terminal (os x commande stock app rapide) qui est. En utilisant IDLE, cela a toujours fonctionné mais n'a pas imprimé le nom de fichier correctement. Pour vous assurer qu'il est vraiment là, je unicode vérifié:

>>>os.listdir(u'listdir')[2] 
u'\u05e2\u05b4\u05d1\u05b0\u05e8\u05b4\u05d9\u05ea.txt' 
+0

je pense qu'il doit faire avec le fait que Windows stocke tous les noms de fichiers en Unicode. voir ma propre réponse partielle –

+0

Sur ma machine, elle fonctionne aussi avec des chaînes Unicode. – PEZ

+0

curieux. si je passe juste pf à imprimer, il jette une exception d'encodage. il doit être attend ascii –

0

Un point d'interrogation est le symbole plus ou moins universel affiché lorsqu'un caractère Unicode ne peut pas être représenté dans un codage spécifique. Votre terminal ou session interactive sous Windows utilise probablement ASCII ou ISO-8859-1 ou quelque chose comme ça. Donc la chaîne actuelle est unicode, mais elle est traduite en ???? lorsqu'il est imprimé sur le terminal. C'est pourquoi cela fonctionne pour PEZ, en utilisant OSX.

+0

Puis-je rendre l'affichage du terminal Windoze Unicode? Que fait OSX pour bien le montrer? –

Questions connexes