2011-08-08 14 views
8

Python 3kは文字列とバイトを厳密に区別しているため、配列sys.argvのコマンドライン引数は文字列として表示されます。引数をバイトとして扱う必要がある場合があります。 Unixで特定の文字エンコーディングにする必要のないパスを渡すときに使用します。sys.argvをPythonのバイト数3k

例を見てみましょう。簡単なPythonの3Kプログラムargv.pyは次のとおりです。

import sys 

print(sys.argv[1]) 
print(b'bytes') 

を、期待される出力生成python3.1 argv.py françaisとして実行されている場合:

français

b'bytes'

注意引数が私のロケールのエンコーディングであるフランセことを。我々は別のエンコーディングに引数を渡すときしかし、我々は、エラーを取得:python3.1 argv.py `echo français|iconv -t latin1`

Traceback (most recent call last): 
    File "argv.py", line 3, in <module> 
    print(sys.argv[1]) 
    UnicodeEncodeError: 'utf-8' codec can't encode character '\udce7' in position 4: surrogates not allowed 

はどのようにして、コマンドライン引数を経由してのPython 3Kプログラムにバイナリデータを合格しなければなりませんか?使用法の例は、他のロケールを使用するユーザーのファイルにパスを渡すことです。あなたはエンコーディングは、引数としてそれを使用するか、またはbytes(sys.argv[1], 'latin-1')を呼び出す知っていれば、

sys.argv[1].encode()のか:

+1

エンコードの問題として自動検出、「UTF-8」と仮定して回避するために、コマンドライン引数を使ってバイナリデータを渡す例です。 – Nope

答えて

2

あなたが行うことができます。

どちらもユニコード文字列のバイト表現を与える必要があります。

デフォルトでは、Python3はUTF-8を使用します。

+2

いいえ、Pythonは必ずしもそうではありません。 UTF8を使用すると、プラットフォームによって異なります。 –

+2

@Lennart Python 3では、デフォルトのエンコーディングとしてUTF-8を使用しています。 – JBernardo

+2

いいえ、そう簡単ではありません。端末のデフォルトエンコーディングは、必ずしもUTF-8である必要はなく、どちらもファイルシステムのデフォルトエンコーディングではありません。私は引用しています」Unixyプラットフォームでは、プラットフォーム依存のデフォルトエンコーディングがあり、LANG環境変数(場合によってはプラットフォーム固有の他のロケール関連環境変数も含む)で設定できます。システムのデフォルトはUTF-8であり、このデフォルトには決してカウントしないでください。これは実際にはWindowsのデフォルトであるcp1252です。しかし、.pyファイルのデフォルトはUTF8です。 –

8

UnicodeDecodeErrorではなく、エラーがUnicodeEncodeErrorであることに注意してください。 Pythonは(PEP 383 surrogateescapeエラーハンドラを介して)コマンドラインで渡された正確なバイトを保存していますが、これらのバイトは有効なUTF-8ではないため、コンソールに書き込むためにエンコードすることはできません。

これに対処するための最良の方法は、次のコード例のように、アプリケーション内のコマンドライン引数を再解釈するために適切なエンコーディングのアプリケーションレベルの知識を使用することである。

$ python3.2 -c "import os, sys; print(os.fsencode(sys.argv[1]).decode('latin-1'))" `echo français|iconv -t latin1` 
français 

os.fsencode関数呼出しコマンドライン引数を処理するときにPythonが自動的に適用する変換を元に戻します。 decode('latin-1')メソッド呼び出しは、適切にデコードされた文字列を取得するために正しい変換を実行します。

os.fsencodeがPython 3.2で追加されました。特にこの種の問題を扱いやすくしました。 Pythonの3.1のために、os.fsencode(sys.argv[1])のための同等の構築物は、sys.argv[1].encode(sts.getfilesystemencoding(), 'surrogateescape')

編集2013年2月です:Pythonの3.2+のために更新され、Pythonはコマンドライン符号化

+0

ロケールがUTF-8であると想定することはできません。したがって、ファイルシステムのエンコーディングを使用してエンコードする必要があります:sys.argv [1] .encode(sys.getfilesystemencoding()、 'surrogateescape')decode( 'latin-1') – mhagger

+2

確かに。 Python 3.3では、 'os.fsencode'を使う方がずっと簡単です。私はsys.argvドキュメントが実際にこの点について説明するべきであることに気付き、バグを提出しました。 – ncoghlan