以下の内容はhttps://nikkie-ftnext.hatenablog.com/entry/release-speech-recognition-3.11.0より取得しました。


メンテナ記:さよならdistutils(SpeechRecognition 3.11.0)

はじめに

ちくせい花火大会のコラボスターマイン、めっちゃきれいでした... アーカイブで見たnikkieです。

ここ数日、SpeechRecognitionでdistutilsを使っている箇所の置き換えを進めていました。

目次

distutils

この記事で初めてdistutilsを聞いたという方は、覚える必要はありません!1
なぜなら、Python 3.12で標準ライブラリから削除されたからです🎉

https://packaging.python.org/en/latest/key_projects/#distutils より

The original Python packaging system, added to the standard library in Python 2.0 and removed in 3.12.

docs.python.org

distutils は 非推奨で、Python 3.12 での除去が予定されています。

What's New In Python 3.12 — Python 3.13.0 ドキュメントより

PEP 632: Remove the distutils package.

この記事を書く中で削除のPEPもあったことを知りました。

SpeechRecognitionとdistutils

発端はこちらのIssue

メンテナの言い分として、今回のリリースの前のSpeechRecognitionは、Python 3.8〜3.11までしかサポートしていません2
3.12でインストールできないのはサポートしていないのだから当然で、feature requestという認識でした。
issueではdistutilsをコードに残した状態で解決するworkaroundが挙がっています3
このたび根本的な対応をした次第です

distutilsを使っている箇所は2箇所でした

$ git checkout 3.10.4
$ git grep distutils
setup.py:from distutils import log
speech_recognition/__init__.py:        from distutils.version import LooseVersion

1️⃣ distutils.logを削除

loggingモジュールを使ったロギングに置き換えました4

該当箇所

# https://github.com/Uberi/speech_recognition/blob/3.10.4/setup.py#L8
from distutils import log
# https://github.com/Uberi/speech_recognition/blob/3.10.4/setup.py#L22
log.info("setting executable permissions on {}".format(output_path))

distutils.logは「Simple PEP 282-style logging」とだけあります。
https://docs.python.org/3.11/distutils/apiref.html#module-distutils.log

実装を見たところ、loggingモジュールは使わずに、loggingモジュール相当のロギングを実装しているようでした。
https://github.com/python/cpython/blob/v3.11.10/Lib/distutils/log.py

ルートロガーではなく子ロガーを作って、INFOログを出力するように置き換えました。
(でも元々から含めて、デフォルトのログレベルWARNINGを変えていなさそうで、INFOレベルのログって出力されるのかちょっと疑問です)

2️⃣ distutils.versionを削除

PEP 632の「Migration Advice」によれば、packagingへの置き換えとなります5
ですが、今回は単に削除しました

該当箇所
https://github.com/Uberi/speech_recognition/blob/3.10.4/speech_recognition/__init__.py#L111-L113

from distutils.version import LooseVersion
if LooseVersion(pyaudio.__version__) < LooseVersion("0.2.11"):
    raise AttributeError("PyAudio 0.2.11 or later is required (found version {})".format(pyaudio.__version__))

distutils.versionには、バージョン番号を表す2つのクラスStrictVersionLooseVersionがあります。
https://github.com/python/cpython/blob/v3.11.10/Lib/distutils/version.py
SpeechRecognitionはPyAudio6 0.2.11以降をインストールしてほしいので、LooseVersionでバージョンチェックをしています。

私の意見は、「ここにバージョンチェックの責務をもたせなくてもよいのではないか」というものです。
パッケージのmetadataの記載を工夫してPyAudio 0.2.11以降がインストールできるように担保できると考え、今回は削除しました。

pip install SpeechRecognition[audio]とインストールしたときに、PyAudio 0.2.11以降がインストールされるようにextraを書いています。
https://github.com/Uberi/speech_recognition/blob/3.11.0/setup.cfg#L10-L11

[options.extras_require]
audio =
    PyAudio >= 0.2.11

終わりに

Python 3.12で削除されたdistutilsをSpeechRecognitionから除きました。
これによりSpeechRecognition 3.11.0はPython 3.12をサポートできています!
distutils、これまでの長い年月、Pythonのパッケージングを支えてくれてありがとう。

手元のPython 3.12の環境にpip install SpeechRecognitionできることを確認しています。
お手元でうまく動かない場合はissueを立てるなどでお知らせください

スターやスポンサーでメンテナ活動を支えていただけるととっても嬉しいです!

応援ください


  1. distutilsのドキュメントには「setuptools は distutils の改良された代替品」とあります。setuptoolsの名前を覚えておくといいかもしれません
  2. 「分類」の「Programming Language」をご覧ください:https://pypi.org/project/SpeechRecognition/3.10.4/
  3. よくまとまっている 「What's New In Python 3.12」に「The third-party Setuptools package continues to provide distutils, if you still require it in Python 3.12 and beyond.」とあるので、ここの方法でうまくいくのかなと認識してます
  4. logging? まかせて!!
  5. ばんくしさんのご本で見たやつ!!(バージョンの扱いが簡単そうでした)
  6. マイクを使う場合に追加でインストールしてほしいパッケージです



以上の内容はhttps://nikkie-ftnext.hatenablog.com/entry/release-speech-recognition-3.11.0より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14