2016-08-19 3 views
0

Python 2の "UTF-8"エンコーディングに関する議論がたくさんあることを知っていますが、私の解決策を見つけることができませんでしたこれまでの問題。私は現在、ファイルの名前を取得してxlwtにハイパーリンクするスクリプトを作成しているので、ファイルはスプレッドシートのクリックでアクセスできます。問題は、これらのファイルの名前の一部に非ASCII文字が含まれていることです。"UTF-8"の代わりにPython 2.7 "latin-1"エンコーディングを使用する

質問1

私は、ファイルの名前を取得するために、次の行を使用していました。フォルダには1つのファイルしかありません。

>>f = filter(os.path.isfile, os.listdir(tmp_path))[0] 

そして

>>print f 
'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc' 
>>print sys.stdout.encoding 
'UTF-8' 
>>f.decode("UTF-8") 
*** UnicodeDecodeError: 'utf8' codec can't decode byte 0xe7 in position 76: invalid continuation byte 

ここでの議論を閲覧から、私は "UTF-8" エンコーディングではありません "\ XE7 \ xe3o" ことに気づきました。次の行を実行することは、この点を裏付けるようです。

>>f.decode("latin-1") 
u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc' 

私の質問は、その後で、なぜF変数がでエンコードされている「Latin-1の」システムのエンコーディングを「UTF-8」に設定されていますか?

質問2

f.decode(「ラテン-1」)は、私が欲しいの出力が得られますが、私はまだスプレッドシートにハイパーリンク関数に変数を供給することができません。

>>data.append(["File", xlwt.Formula('HYPERLINK("%s";"%s")' % (os.path.join(dl_path,f.decode("latin-1")),f.decode("latin-1")))]) 
*** FormulaParseException: can't parse formula HYPERLINK("u'H:\\Mad Lab\\SE Doc Crawler\\bovespa\\download\\521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's;"u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc's) 

明らかに、閉じる二重引用符が食べられ、「s」接尾辞で置き換えられました。誰かがここで何が起こっているのかを説明するのに役立つことができますか? 0.0

ああ、誰かが上記質問2の解決策を提案できれば、私は非常に感謝しています。あなたは私の週末を悲惨から救ったでしょう!

ありがとうございます!

+0

ファイルシステムのエンコーディングは、常にロケール(stdoutとstdinのエンコーディング)と異なる場合があります。代わりに 'sys.getfilesystemencoding()'を見てください。 –

+0

IDLE、PyCharm、Intellij、EclipseのようなコンソールやIDEを使用している場合は、どのオペレーティングシステムを使用しているのか教えてください。 –

+0

@MartijnPieters sys.getfilesystemencoding()throws "mbcs" – kerwei

答えて

0

紛らわしいエンコーディングの世界へようこそ!少なくともファイルのエンコーディング、ターミナルのエンコーディング、ファイル名のエンコーディングがありますが、これらの3つはすべて異なる可能性があります。

Python 2.xでは、コード化されたstrからUnicode文字列(strとは異なる)を取得することが目標です。問題は、strで使用されているエンコーディングを常に知っているとは限らないため、デコードが難しいことです。

ファイル名を取得するためにlistdir()を使用して、文書化が、しばしば見落とさ癖があります - あなたはstrlistdir()には、あなたがstrの背中をエンコードます渡す場合。これらはあなたのロケールに応じてエンコードされます。 Windowsでは、これらは8ビット文字セット(windows-1252など)になります。

代わりに、listdir()にUnicode文字列を渡してください。

など。

os.listdir(u'C:\\mydir') 

uプレフィックス

これは正しくデコードされたUnicodeのファイル名を返します。 WindowsおよびOS Xでは、環境ロケールが混乱していない限り、これはかなり信頼できます。あなたのケースでは

listdir()は返します:

u'521001ldrAvisoAcionistas(Retifica\xe7\xe3o)_doc' 

ここでも、u接頭辞に注意してください。これを修正してPyCharmコンソールに表示できるようになりました。

など。質問2については

f = filter(os.path.isfile, os.listdir(tmp_path))[0] 
print f 
+0

説明をありがとう!私はフォルダからファイルを読み込んでいるので、文字列リテラルで 'u'接頭辞を使用する選択肢はありません。どちらにせよ、あなたの答えは正しい方向で私を指摘しました。私は[link](http://nedbatchelder.com/text/unipain.html)のおかげで、エンコーディングの話題を少し良く理解していると思います。私はこれを解決策としてマークします。 – kerwei

+0

問題ありません。要は、 'listdir()'でリストしたいディレクトリを最初に渡すときは、 'u'''や他の手段で作成したUnicodeオブジェクトを使います。結果はUnicodeになります。 –

0

、私はさらに調査しなかったが、ちょうど起因する時間的制約に、Unicode文字列ではなく、xlwtオブジェクトとして出力を印刷。私はここで何がうまくいかなかったかを理解することなく、プロジェクトを続けることができます。その意味で、上記2つの質問に答えました。

関連する問題