3 ポイント 投稿者 GN⁺ 2024-04-28 | 1件のコメント | WhatsAppで共有

PEP 686 - Python 3.15からUTF-8モードをデフォルトで有効化

  • UTF-8が事実上の標準テキストエンコーディングになりつつある
    • PythonソースファイルのデフォルトエンコーディングはUTF-8
    • JSON、TOML、YAMLはUTF-8を使用
    • Visual Studio Code、Windowsメモ帳など、ほとんどのテキストエディタはデフォルトでUTF-8を使用
    • ほとんどのWebサイトやインターネット上のテキストデータはUTF-8を使用
    • Node.js、Go、Rust、Javaなど、多くの人気プログラミング言語もデフォルトでUTF-8を使用
  • デフォルトエンコーディングをUTF-8に変更すると、Pythonが他の言語と相互運用しやすくなる
  • 多くのUnix系Python開発者は、デフォルトエンコーディングがプラットフォームによって異なるという事実を忘れがち
    • UTF-8でエンコードされたテキストファイル(JSON、TOML、Markdown、Pythonソースファイルなど)を読むときに encoding="utf-8" を指定しない
    • 一貫しないデフォルトエンコーディングにより多くのバグが発生する

PEP 686の主な変更点

  • Python 3.15からUTF-8モードがデフォルトで有効になる
    • ユーザーは引き続き PYTHONUTF8=0 または -X utf8=0 を設定してUTF-8モードを無効化できる
  • locale.getencoding() を追加
    • UTF-8モードに関係なくロケールエンコーディングを取得するためのAPI
    • warn_default_encoding オプションが指定されると、locale.getpreferredencoding()open() と同様に EncodingWarning を発生させる(PEP 597参照)
  • encoding="locale" オプションを修正
    • TextIOWrapperencoding="locale" が指定された場合、UTF-8モードでもロケールエンコーディングを使用する必要がある

後方互換性

  • ほとんどのUnixシステムはUTF-8ロケールを使用しており、PythonはロケールがCまたはPOSIXのときにUTF-8モードを有効にするため、この変更は主にWindowsユーザーに影響する
  • Pythonプログラムがデフォルトエンコーディングに依存している場合、この変更によって UnicodeError、文字化け、または静かなデータ破損が発生する可能性がある
  • 後方互換性の問題を解決するための指針:
    1. UTF-8モードを無効化する
    2. EncodingWarning(PEP 597)を使ってUTF-8モードの影響を受けるすべての箇所を見つける
      • encoding オプションが省略されている場合は、encoding="utf-8" または encoding="locale" の使用を検討
      • locale.getpreferredencoding() が使われている場合は、"utf-8" または locale.getencoding() の使用を検討
    3. UTF-8モードでアプリケーションをテストする

GN⁺の意見

  • このPEPは、PythonのデフォルトエンコーディングをUTF-8に統一し、他の言語やシステムとの相互運用性を高めることを目的としている。これにより、Pythonがグローバルな開発環境でより円滑に使えるようになるはず
  • ただし、この変更は既存のPythonプログラムの後方互換性に影響する可能性がある。特にWindows環境で動作するプログラムでは注意が必要
  • 開発者は EncodingWarning を活用して影響を受ける箇所を特定し、encoding オプションを明示的に指定するなどの方法で対応する必要がある
  • 長期的には、この変更はPythonエコシステムに好影響を与えると予想される。ただし短期的には、一部のプロジェクトで移行コストが発生する可能性がある
  • 開発者はPython 3.15へのアップグレードを計画する際、この変更点を考慮し、必要に応じて後方互換性のための適切な対策を講じるべき

1件のコメント

 
GN⁺ 2024-04-28
Hacker Newsの意見
  • Pythonのデフォルトのテキストファイルエンコーディングがプラットフォームごとに異なるのは、長い間問題だった
  • ファイルシステムのエンコーディング問題は別件であり、今回の変更では扱われない
  • システムのデフォルト値に依存するのはよくない。想定と異なる可能性があるため
  • 過去にUbuntuとinit.dスクリプトで問題があった。rootとして実行されるJava実行スクリプトが一般ユーザーと異なるエンコーディングを使い、問題が発生した
  • 最近では問題になりにくいが、OSにこれを任せるのは避けるべき。UTF-8以外のエンコーディングを使うのは意図しないケースである可能性が高い
  • 明示的に指定せずOS設定に依存するのはよくない
  • 今回の変更は良い方向。壊れるコードは単純に修正したほうがよい
  • 内容破損バグの可能性がある状態のままにしておくよりよいと思う

ここ数十年でますます真実になりつつある経験則: "charset" の設定がUTF-8でないなら、それは間違っている

  • Python 2はcharsetに縛られず常にうまく動いていたが、Python 3の改善は改善以上のものだった

  • Python 3スクリプトとPython 2スクリプトを見分ける方法:

    • "utf-8" という文字列があればPython 3
    • C.UTF-8 ロケールでしか動かなければPython 3
  • 今回の変更は歓迎すべきもので、Python 3を「改善」するように見える

  • これはPython 3からデフォルトだったと思っていた

Node.js、Go、Rust、Javaを含む多くの人気言語は、デフォルトでUTF-8を使う

  • JavaがUTF-16からUTF-8へ移行したのは知らなかった

  • CPythonの内部エンコーディングがUTF-8なのかは分からない

  • Pythonの文字列はインデックス参照が可能だが、ランダムアクセスはまれなので、必要なときに遅延インデックス化するのがよさそう

  • 1文字ずつ前後に移動するだけならインデックスは不要

  • したがって、内部的にUTF-8表現は可能だと思われる

  • なぜ utf-8-sig ではないのか? BOMを選択的に処理してくれるので便利

  • UTF-8に関連して言えば、Linuxフレームバッファはずっと前からまともなUTF-8サポートを備えているべきだった

  • GNU Hurdは2007年ごろから、UTF-8をサポートするより良い「ターミナルコンソール」を持っていた

  • 2024年になってようやくこうした変化が来るとは

  • 良い変化。あとはJSだけがUTF-8に移行すればよいが、1995年に書かれたコードとの互換性を保たなければならず、改善が難しい

多くのUnix系Python開発者は、デフォルトエンコーディングがプラットフォームごとに異なることを忘れ、UTF-8のテキストファイルを読むときに encoding="utf-8" を明示しない

  • 「忘れる」というより、きちんと認識していないのだと思う
  • 明示的に要求しない限り、PythonはどこでもUTF-8だけを使うものだと思っていた