Python 3のサポート—ドキュメントをクリックします
Python3のサポート
ClickはPython3をサポートしていますが、他のすべてのコマンドラインユーティリティライブラリと同様に、Python3のUnicodeテキストモデルの影響を受けます。 ドキュメント内のすべての例は、Python2.xとPython3.4以降の両方で実行できるように作成されています。
Python3の制限
現時点では、ClickはPython3でいくつかの問題を抱えています。
Unixのコマンドラインは伝統的にバイト単位であり、Unicodeではありません。 これらすべてのエンコーディングのヒントがありますが、一般的にこれが壊れる可能性のある状況がいくつかあります。 最も一般的なものは、異なるロケールのマシンへのSSH接続です。
誤って構成された環境は、ラウンドトリップサロゲートエスケープのサポートがないため、現在Python3でさまざまなUnicodeの問題を引き起こす可能性があります。 これはClick自体では修正されません!
詳細については、 Python3サロゲート処理を参照してください。
Python 3の標準入出力は、デフォルトでUnicodeモードで開かれます。 クリックは、特定の状況でバイナリモードでストリームを再度開く必要があります。 これを行うための標準化された方法がないため、これが常に機能するとは限りません。 主に、これはコマンドラインアプリケーションをテストするときに問題になる可能性があります。
これはサポートされていません:
sys.stdin = io.StringIO('Input here') sys.stdout = io.StringIO()
代わりに、これを行う必要があります。
input = 'Input here' in_stream = io.BytesIO(input.encode('utf-8')) sys.stdin = io.TextIOWrapper(in_stream, encoding='utf-8') out_stream = io.BytesIO() sys.stdout = io.TextIOWrapper(out_stream, encoding='utf-8')
その場合、ラッパーはそのメソッドを転送しないため、バッファの内容にアクセスする場合は、
sys.stdout.getvalue()
ではなくout_stream.getvalue()
を使用する必要があることに注意してください。
Python2と3の違い
Clickは、両方の言語のベストプラクティスに従って、Python2とPython3の違いを最小限に抑えようとします。
Python 2では、次のことが当てはまります。
sys.stdin
、sys.stdout
、およびsys.stderr
はバイナリモードで開かれますが、状況によってはUnicode出力をサポートします。 Clickはこれを覆そうとはしませんが、ストリームをUnicodeベースにするためのサポートを提供します。sys.argv
は常にバイトベースです。 クリックすると、すべての入力タイプにバイトが渡され、必要に応じて変換されます。 STRING タイプは、最も適切なエンコーディングを試行することにより、入力値を文字列に適切にデコードします。- ファイルを処理する場合、ClickはUnicode APIを経由せず、代わりにオペレーティングシステムのバイトAPIを使用してファイルを開きます。
Python 3では、次のことが当てはまります。
sys.stdin
、sys.stdout
、およびsys.stderr
は、デフォルトでテキストベースです。 Clickがバイナリストリームを必要とする場合、基になるバイナリストリームを検出しようとします。 これがどのように機能するかについては、 Python3の制限を参照してください。sys.argv
は常にUnicodeベースです。 これは、Clickの型への入力値のネイティブ型がUnicodeであり、バイトではないことも意味します。これは、端末が正しく設定されておらず、Pythonがエンコーディングを認識しない場合に問題を引き起こします。 その場合、Unicode文字列には、サロゲートエスケープとしてエンコードされたエラーバイトが含まれます。
ファイルを処理する場合、Clickは、オペレーティングシステムの報告または推測されたファイルシステムエンコーディングを使用して、常にUnicodeファイルシステムAPI呼び出しを使用します。 ファイル名はサロゲートでサポートされているため、環境が正しく構成されていなくても、 File タイプでファイルを開くことができるはずです。
Python3サロゲート処理
Click in Python 3は、標準ライブラリ内のすべてのUnicode処理を実行し、その動作の影響を受けます。 Python 2では、ClickがすべてのUnicode処理を実行します。つまり、エラーの動作に違いがあります。
最も明白な違いは、Python 2ではUnicodeが「正しく機能する」のに対し、Python3では特別な注意が必要なことです。 これは、Python 3ではエンコーディングの検出がインタプリタで行われ、Linuxやその他の特定のオペレーティングシステムでは、エンコーディングの処理に問題があるためです。
フラストレーションの最大の原因は、initシステム(sysvinit、upstart、systemdなど)、デプロイメントツール(salt、puppet)、またはcronジョブ(cron)によって呼び出されるClickスクリプトが、Unicodeロケールがエクスポートされない限り機能しないことです。
Clickがそのような環境に遭遇した場合、それ以上の実行が妨げられ、ロケールの設定が強制されます。 これが行われるのは、クリックが呼び出されるとシステムの状態を認識できず、PythonのUnicode処理が開始される前に値を復元できないためです。
Python 3でこのようなエラーが表示された場合:
Traceback (most recent call last):
...
RuntimeError: Click will abort further execution because Python 3 was
configured to use ASCII as encoding for the environment. Either switch
to Python 2 or consult the Python 3 section of the docs for
mitigation steps.
ノート
Python 3.7以降では、 PEP 538 および PEP 540 のおかげで、多くの場合RuntimeError
を取得できなくなります。 ]、未構成の環境でのデフォルトの仮定を変更しました。
Python3がASCIIデータに制限されていると見なす環境を扱っています。 これらの問題の解決策は、コンピューターが実行されているロケールによって異なります。
たとえば、ドイツ語のLinuxマシンを使用している場合は、ロケールをde_DE.utf-8
にエクスポートすることで問題を修正できます。
export LC_ALL=de_DE.utf-8
export LANG=de_DE.utf-8
米国のマシンを使用している場合は、en_US.utf-8
が最適なエンコーディングです。 一部の新しいLinuxシステムでは、ロケールとしてC.UTF-8
を試すこともできます。
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
一部のシステムでは、 UTF-8 を UTF8 と記述する必要があり、その逆もあると報告されています。 サポートされているロケールを確認するには、locale -a
を呼び出すことができます。
locale -a
Pythonスクリプトを呼び出す前に、これを行う必要があります。 この理由に興味がある場合は、Python3バグトラッカーのディスカッションに参加できます。
- ASCIIは悪いファイルシステムのデフォルトエンコーディングです
- デフォルトのエラーハンドラーとしてsurrogateescapeを使用する
- Python3はCロケールでUnicodeエラーを発生させます
- LC_CTYPE = C:pydocは端末を使用できない状態のままにします(これは、ポケットベルのサポートがstdlib pydocモジュールによって提供されるため、Clickに関連します)
注(Python 3.7以降):ロケールが適切に構成されていない場合でも、Python 3.7プログラムはデフォルトのロケールを選択するのに優れているため、Python 3.7Clickでは上記の例外は発生しません。 これは、ロケールが正しく構成されていない可能性があるという一般的な問題を変更するものではありません。
Unicodeリテラル
Click 5.0以降、Python2でのunicode_literals
の将来のインポートの使用に関する警告が表示されます。 これは、Unicodeデータを処理できないAPIに導入することにより、意図せずにバグを引き起こすというこのインポートの悪影響のために行われました。 この問題のいくつかの例については、このgithubの問題に関する説明を参照してください: python-future#22 。
クリックコマンドを定義するファイルまたはクリックコマンドを呼び出すファイルでunicode_literals
を使用すると、警告が表示されます。 unicode_literals
を使用せず、代わりにUnicode文字列に明示的なu
プレフィックスを使用することを強くお勧めします。
警告を無視して、自分の危険でunicode_literals
を引き続き使用する場合は、次のように警告を無効にすることができます。
import click
click.disable_unicode_literals_warning = True