Python3.12のpipがバグってる件&とりあえずの修正方法
始めに
2023/10/2に約一年ぶりのメジャーアップデートであるPython3.12.0が公開されました。 昨日から使おうとインストールしたところ、pythonパッケージ管理用アプリのpipでエラーが発生し、 そのエラーの対応方法も発見しましたので、まとめておきます。
検証した環境
その1
OS: Windows10 CPU: core i5-11600KF MEM: DDR4-3200 32GB GPU: GTX1660Ti
その2
上記マシン上にインストールしたwsl OS: Ubuntu 20.04-LTS
仮想環境
共にvirtualenvを用いた仮想環境を用意して検証しています。
発生している現象
Python3.12.0の環境で、pipを使うとエラーが発生する。
pip list
や
pip install numpy
で
Traceback (most recent call last): File "/root/pythonproject/test/bin/pip", line 8, in <module> sys.exit(main()) ^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/cli/main.py", line 70, in main return command.main(cmd_args) ^^^^^^^^^^^^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/cli/base_command.py", line 101, in main return self._main(args) ^^^^^^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/cli/base_command.py", line 216, in _main self.handle_pip_version_check(options) File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/cli/req_command.py", line 179, in handle_pip_version_check session = self._build_session( ^^^^^^^^^^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/cli/req_command.py", line 125, in _build_session session = PipSession( ^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/network/session.py", line 343, in __init__ self.headers["User-Agent"] = user_agent() ^^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/network/session.py", line 175, in user_agent setuptools_dist = get_default_environment().get_distribution("setuptools") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py", line 188, in get_distribution return next(matches, None) ^^^^^^^^^^^^^^^^^^^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py", line 183, in <genexpr> matches = ( ^ File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/metadata/base.py", line 612, in iter_all_distributions for dist in self._iter_distributions(): File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py", line 176, in _iter_distributions for dist in finder.find_eggs(location): File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py", line 144, in find_eggs yield from self._find_eggs_in_dir(location) File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py", line 111, in _find_eggs_in_dir from pip._vendor.pkg_resources import find_distributions File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2164, in <module> register_finder(pkgutil.ImpImporter, find_on_path) ^^^^^^^^^^^^^^^^^^^ AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'?
のようなエラーが発生。
pip -V
は普通に動きました。
修正方法
この方法は正式な方法ではありません。利用する際には自己責任で実行してください。
一段階目
pipのコードを二種類編集します。 pipはpythonによって実装されており、pythonベースのエラーが出てくるため、それに従って修正すればOKです。 見るべきはエラー出力下4行です。
File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2164, in <module> register_finder(pkgutil.ImpImporter, find_on_path) ^^^^^^^^^^^^^^^^^^^ AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'?
VScodeでは、エラーが出ているファイル名にカーソルを合わせるとそこからファイルへアクセスできます。
pip/_vendor/pkg_resources/__init__.py
のファイルの
register_finder(pkgutil.ImpImporter, find_on_path)
を
register_finder(pkgutil.zipimporter, find_on_path)
に変更します。 その後、もう一度
pip list
でエラーを確認します。すると、少し出力が変化し、以下のようになっているはずです。
File "/root/pythonproject/test/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2315, in <module> register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) ^^^^^^^^^^^^^^^^^^^ AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'?
下4行が以上のようになっていたら、pip/_vendor/pkg_resources/__init__.py
のファイルの
register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
を
register_namespace_handler(pkgutil.zipimporter, file_ns_handler)
に変更します。 この状態で、
pip list
を実行すると、エラーが出ずに正常に動くはずです。 これで第一段階目が完了です。 これでも一応動くのですが、正常なコードではないためpipをアップグレードすることを推奨します。
第二段階目
pip list
を実行すると、モジュールが並んだ後に
[notice] A new release of pip is available: 23.0.1 -> 23.3.1 [notice] To update, run: pip install --upgrade pip
といった表示が出ると思います。この二行目の指示通り、
pip install --upgrade pip
を実行することで、pipが最新版にアップグレードされ、正常に動くようになります。 また、windows環境の場合は、アップグレード用のコマンドは
python -m pip install --upgrade pip
のようになります。
想定されるバグの原因
python3.12でpkgutilに変更がかかったことが問題だと考えられます。
終わりに
最後までお読みいただきありがとうございました。 今回の手法で修正できなかった・もっと簡単な修正法が見つかったという方はぜひコメントをよろしくお願いします。
Pythonを100倍の速度で実行する方法 ~Codonを試してみた~
Codonとは
Codonというのは、新しくできたPythonのコンパイラです。.pyファイルを機械語に翻訳することで、10倍から100倍の高速化を実現しています。
ただ、全く同じように記述できるわけではなく、動的型付けができない・外部モジュールの利用が少し大変、などの問題点も存在します(後述)。それでも使い方を理解すれば強力な武器になることは間違いありませんので、ぜひ最後まで読んで実際に使ってみていただければと思います。
対応環境・インストール方法
詳しいことはWelcome to Codon - Codonの公式リンクからいろいろ確認してください。記事作成現在では、MacかLinuxでのみ利用可能となっています。筆者は主にWindowsでの開発をしているので、Windows上にwslを立ててその中にLinux版のCodonを入れました。
以下のインストール方法はLinux版の方法になります。
/bin/bash -c "$(curl -fsSL https://exaloop.io/install.sh)" echo 'export PATH="$HOME/.codon/bin:$PATH"' >> ~/.bashrc source ~/.bashrc
上の3行を実行すると、インストールできてるはずです。
codon -version
で0.15.5のような数字(この数字は筆者環境)が出れば完了しています。
実際に実行&ベンチマーク
codon run -release main.py
の形で実行します。
-lreleaseのオプションを付けることで、より最適化された形にコンパイルすることができます。
バイナリファイルを生成したい場合には、
codon build -release main.py
で、mainという実行ファイルが生成され、
./main
で実行できます。
実行ファイル名を指定したい場合には、
codon build -release main.py -o prime
のように、-oのオプション(gccとかと同じ)を付けることで指定できます。
今回は、以前使った素数数え上げプログラム(番外編:サーバーを借りた話 - chachaの備忘録参照)を改良したものを使います。
import math import time def isPrime (x,l): if x%2==0: return False sqr=math.sqrt(x) for i in l: if x%i==0: return False if i>sqr: break return True def main(): try: l=list(capacity=1000000) except: l=list() l.append(2) start = time.perf_counter() ip=10000000 for i in range(3,ip+1): if isPrime(i,l)==True: #print(i) l.append(i) print("end") print(time.perf_counter() - start) if __name__=="__main__": main()
main関数の最初のtry部分は、codonでリスト長を指定するためのものと、pythonで指定せずにリストを用意するためのものになっています。
実行環境としては、
OS: windows10+wsl(ubuntu20.04TLS)
CPU:Core i5-11600KF
MEM:DDR4-3200 32GB
といった感じのPCを使います。
Python3側はpython3.11.2(記事作成時最新)、Codon側はcodon0.15.5(記事作成時最新)で事前ビルドした上で実行していきます。
処理系 | 実行時間(秒) |
python3 | 10.59195 |
codon | 0.6533494 |
ともに5回実行してその平均を求めたものですが、言葉通り桁違いの性能ですね、codon。16倍のスピードで実行できてるみたいです。
外部ライブラリの使い方
現在の状態でも十分使えるのですが、標準モジュール以外のモジュールが使えません(numpyとかpandasとか)。pipでインストールできるモジュールを使う方法をまとめます。
外部モジュールを使うには、共有ライブラリというものと連携させる必要があります。まず、以下のコマンドでlibpython3.8.soといったようなファイルを探します。
find / -name "libpython*.so"
だいたい、
/usr/lib/x86_64-linux-gnu/libpython3.8.so /usr/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.so
みたいな感じで出力されると思います。
その中のどれか(筆者は一番上のもの)をCODON_PYTHONの環境変数に以下のコマンドで設定します。
export CODON_PYTHON=/usr/lib/x86_64-linux-gnu/libpython3.8.so
こうすることで、python3.8にインストールしたモジュールを利用することができます。
利用方法なのですが、pythonで実行するときと少しimport文の書き方が変わってきます。
from python import numpy
のように、from pythonを付ける必要があります。
codonからnumpyを呼び出す際のスピードも計ってみようと思い、以下のコードで速度を計ってみます。1行目、2行目は処理系に合わせてコメントアウトを付けたり外したりします。
from python import numpy as np#codon用 #import numpy as np#python用 import time start = time.perf_counter() l=np.ones(1000000) ans=0 for i in l: ans+=i print(ans) print(time.perf_counter() - start)
処理系 | 実行時間(秒) |
python3 | 0.07621 |
codon | 1.31325 |
このようになりました。codonは毎回numpyを呼び出しているのか、codonのほうが遅いという結果になりました。
今後numpyはcodonにネイティブ対応するとのことですが、今のところnumpyが必要な環境ではcodonを使う恩恵はあまり感じないのかなと思います。
注意点
今回は起こりませんでしたが、codonが静的型付けをする以上、動的に型を変化させるようなコードを実行することはできません。また、複数の型を一つのリストに入れることもできないため、pythonの特徴ともいうべき、型を意識しないコーディングが不可能になっています。
また、ライセンスがBusiness Source License 1.1であるため、非商用でのみ利用可能となっています(2025/11からは商用利用も可能なApache Licenseに移行)。そういった点もお気を付けください。
感想
一言でいうと、めちゃくちゃ楽しいです。今後numpyとかpandasとかが普通に使えるようになり、商用利用も可能になったら一気に広まるんだろうなぁと思ってます。
ただ、やはり型付けしっかりしないといけないのがめんどくさいなぁと(pythonユーザーの業)。まあコンパイルエラーでしっかりと教えてくれるので、それを読んで直せる人なら特に違和感もなく使っていけると思います。僕は今後使っていく(予定)です。
では今日はこんなところで。ご質問やご意見があればコメントへお願いします。ではでは~
参考にさせていただいたリンク集
あなたのPythonを100倍高速にする技術 / Codon入門【Codon】Pythonコンパイラを試してみた
Welcome to Codon - Codon
番外編:サーバーを借りた話
サーバー借りました
友人がマイクラをマルチプレイしたいと言い出したのでサーバーを借りることにしました。プレイしてないときは裏で計算回してもいいよって言われたので、そっちの話を色々していこうかと思います。
性能
色々検討した結果KAGOYAのVPSを借りることにしました。性能の割に安かったんですよ(一日55円 月額最大1540円)。スペックはCPU4コア、メモリ4GB、ストレージ80GBになります。このスペック、他の会社だと月3000円くらいするところもあります。執筆時点で2週間くらい運用していますが性能も十分でとても満足しています。
OSもCent OS各種、Ububtu各種、Windows Server各種整っているので使い慣れた環境をすぐに利用できます。今回は使い慣れたUbuntu 20.04を使いました。
クライアント側の準備
サーバーを動かすためにはクライアント側(サーバーに指示を出すパソコン)の準備もある程度必要です。最低限動かすだけならWindowsのコマンドプロンプト、Macのターミナルでも可能なのですが、楽に動かすためにも専用のソフトウェアを入れることをお勧めします。特にKAGOYAではRSA鍵を用いた認証(パスワード認証よりも強固)を採用できるので、それに対応しているソフトの利用価値がとても高いです。
一つ目がTera Term。SSH用のソフトウェアです。コマンドプロンプトと全く同じ感じで使用できます。最新版がリンクからダウンロードできます。
で二つ目、Cyberduck。こちらはあまり一般的ではないのですが、GUIを利用してサーバーとファイルのやり取りをするためのソフトウェアになります。視覚的にファイルのやり取りが可能なので、一旦設定ファイルを落として、クライアント側で編集、そのあとアップロードする、ってするだけで面倒なコマンドを一切使わずにファイル編集ができたりします。実際に回したプログラムも、パソコンで書いてCyberduckを用いてアップロードしています。
この二つのソフトはサーバーを自分で建てようって思うような人なら簡単に利用できる簡単なものなので、ぜひ使ってみてください。
実際に回してみた
ちょうど友人が忙しい日々が続いていたので、ちょっと大きめの計算をさせることに。で、用意したのが以下のプログラムです。
入力された数以下の素数を全て求めていくものになります。メモリが重くなることを嫌って、素数リストをプログラム内に作らず、一つ一つテキストファイルに保存していく方式で動かしてます(めっちゃ遅い)。これを10憶まで回したところ、1日半くらいで終わりました。ぶっちゃけ想像の倍くらい早かった。Python遅いから3~4日かかると思ってました。結果として478MBほどの化け物テキストファイルが生成されてたわけですがチェックしたところ完璧に生成されていたようです(こちらもサーバーでチェックプログラムを動かし、2日ほどで確認 単純なアルゴリズムだったのでかなり時間かかった)。
まとめ
ちょっと大きめの計算をさせたいけどどうしようって方、居ると思うんですよ。PC内で回そうとするとその処理にPC取られちゃいますからね。しかもスリープ状態だったら処理とまるし。
なので中規模くらいの計算させたい方にはVPS、お勧めな方法だと思います。大規模ってなってくると自前でワークステーションとか用意した方がいいってなるんでしょうがね。価格的にも月~2000円なら出せるって人多いと思うんです。なんなら500円とかでも借りられますからね。ぜひお試しください。
サーバー設定とかの技術的な話は今後ちょくちょく書いていく(予定)ので、サーバーわからないよって方はしばしお待ちを。
今回はこんなところで終わろうと思います。ご意見、ご質問等ありましたら、コメント欄の方へお願いします。Pythonアプリ開発日記(今名付けた)の方も少しずつ進んではいるのであまり期待せずお待ちいただければ幸いです。ではでは~。
環境構築
今まではなんとなくでプログラムを書いていたんですが、今後アプリケーション開発に手を出すことになるので、しっかりと環境を組んでいきたいと思います。
今回やっていくのはvirtualenvによるpython仮想環境の用意になります。
注意として、今回はWindows10で環境を構築しています。Linux、Mac等別のOSで作業をしている方は別の方法が必要になりますのでご注意ください。
1.virtualenv(venv)の準備
さて、一つ目は仮想環境の準備です。仮想環境とは何ぞやって感じではあるのですが、簡単に言うとコンピューターの内部で仮想的に実行環境を整えるもので、よくモジュールなどを案件ごとに管理するために使います。pythonで使える仮想環境としてはpipenv等他にもあるのですが、今回はvirtualenvを使用していきます。
pythonは導入されているものとして話を進めますので、まだ導入していない方は以下のリンクからダウンロード、インストールをしてください。
ここからはPowerShellを使って設定を行っていきます。
まず、pipを使ってvirtualenvをインストールしていきます。
pip install virtualenv
↑このコマンドでインストールします。
virtualenv --version
↑このコマンドを実行した際に"virtualenv 20.15.1~"(数字はバージョンによって違います)と出たらインストール成功です。
上のコマンドは完全にコピペ実行でOKです。
2.環境作成
次に、実際に使う仮想環境を作っていきます。
まずは、フォルダの作成からやっていきます。
python -m virtualenv <フォルダ名>
↑このコマンドでフォルダを作成します。<フォルダ名>のところには作りたいフォルダ名(プロジェクト名)などを入れるとわかりやすくなります。今回の場合はpyにしています。これでフォルダができました。
その上で、仮想環境を有効化するために
<フォルダ名>\Scripts\activate.ps1
を実行します。これで、コマンドラインの左側が(<フォルダ名>) PS ~のようなものに変化していれば成功です。
3.実行
では実際に環境内でプログラムを実行してみましょう。プログラムファイルは、作成したフォルダ直下(今回の場合はpyの中)にいれます。
今回はHello Virtualenv World!と表示するものを用意します。
作成したフォルダに移動し、
python <プログラム名>.py
で実行してみてください。以下の画像のように出力されれば成功になります。
実際の使い方としてはこのように仮想環境を起動している段階でpip等でモジュールをインストールすると、他のフォルダに影響を及ぼすことなくインストールすることが可能になります。
4.閉じ方
最後に仮想環境の閉じ方です。
deactivate
こちらのコマンドで仮想環境を閉じることができます。
5.二回目以降
二回目以降は上に書いたことを全てする必要はありません。起動すること、そして閉じることの二つのみでOKです。
起動するとき
開きたいフォルダの入っているフォルダ(今回の場合はC:\Users\chach\python)で
<フォルダ名>\Scripts\activate.ps1
のコマンドを実行してください。
閉じるとき
仮想環境に入っている状態で
deactivate
のコマンドを実行してください。
6.終わりに
今回はwindows環境下でpythonを仮想環境virtualenvで開発していく方法をまとめていきました。少しでも参考になれば幸いです。
ご挨拶
はじめまして、情報系の大学に通っているchachaと申します。
pythonの勉強を独学で行っており、その中で先人達のブログにお世話になりました。学んだものを纏めておき、またインターネットに学んだものを少しでも還元したいと思い、このブログをはじめました。
初めての投稿ですのでミスなども起こりうるでしょうが、温かい目でお応援いただければ幸いです。
さて、今後の目標なのですが、11月に発売されるポケモンSVの対戦支援ツールの開発の開発を目指していきたいと思っています。どういった内容になるかはわかりませんが、GUI、SQLなど様々なものを利用していく予定です。どこまでできるかわかりませんが、応援よろしくお願いいたします。