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の公式リンクからいろいろ確認してください。記事作成現在では、MacLinuxでのみ利用可能となっています。筆者は主に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

番外編:サーバーを借りた話

サーバー借りました

 友人がマイクラマルチプレイしたいと言い出したのでサーバーを借りることにしました。プレイしてないときは裏で計算回してもいいよって言われたので、そっちの話を色々していこうかと思います。

性能

 色々検討した結果KAGOYAVPSを借りることにしました。性能の割に安かったんですよ(一日55円 月額最大1540円)。スペックはCPU4コア、メモリ4GB、ストレージ80GBになります。このスペック、他の会社だと月3000円くらいするところもあります。執筆時点で2週間くらい運用していますが性能も十分でとても満足しています。

 OSもCent OS各種、Ububtu各種、Windows Server各種整っているので使い慣れた環境をすぐに利用できます。今回は使い慣れたUbuntu 20.04を使いました。

クライアント側の準備

 サーバーを動かすためにはクライアント側(サーバーに指示を出すパソコン)の準備もある程度必要です。最低限動かすだけならWindowsコマンドプロンプトMacのターミナルでも可能なのですが、楽に動かすためにも専用のソフトウェアを入れることをお勧めします。特にKAGOYAではRSA鍵を用いた認証(パスワード認証よりも強固)を採用できるので、それに対応しているソフトの利用価値がとても高いです。

 一つ目がTera TermSSH用のソフトウェアです。コマンドプロンプトと全く同じ感じで使用できます。最新版がリンクからダウンロードできます。

 で二つ目、Cyberduck。こちらはあまり一般的ではないのですが、GUIを利用してサーバーとファイルのやり取りをするためのソフトウェアになります。視覚的にファイルのやり取りが可能なので、一旦設定ファイルを落として、クライアント側で編集、そのあとアップロードする、ってするだけで面倒なコマンドを一切使わずにファイル編集ができたりします。実際に回したプログラムも、パソコンで書いてCyberduckを用いてアップロードしています。

 この二つのソフトはサーバーを自分で建てようって思うような人なら簡単に利用できる簡単なものなので、ぜひ使ってみてください。

実際に回してみた

 ちょうど友人が忙しい日々が続いていたので、ちょっと大きめの計算をさせることに。で、用意したのが以下のプログラムです。

PrimeList.py

入力された数以下の素数を全て求めていくものになります。メモリが重くなることを嫌って、素数リストをプログラム内に作らず、一つ一つテキストファイルに保存していく方式で動かしてます(めっちゃ遅い)。これを10憶まで回したところ、1日半くらいで終わりました。ぶっちゃけ想像の倍くらい早かった。Python遅いから3~4日かかると思ってました。結果として478MBほどの化け物テキストファイルが生成されてたわけですがチェックしたところ完璧に生成されていたようです(こちらもサーバーでチェックプログラムを動かし、2日ほどで確認 単純なアルゴリズムだったのでかなり時間かかった)。

まとめ

 ちょっと大きめの計算をさせたいけどどうしようって方、居ると思うんですよ。PC内で回そうとするとその処理にPC取られちゃいますからね。しかもスリープ状態だったら処理とまるし。

 なので中規模くらいの計算させたい方にはVPS、お勧めな方法だと思います。大規模ってなってくると自前でワークステーションとか用意した方がいいってなるんでしょうがね。価格的にも月~2000円なら出せるって人多いと思うんです。なんなら500円とかでも借りられますからね。ぜひお試しください。

 サーバー設定とかの技術的な話は今後ちょくちょく書いていく(予定)ので、サーバーわからないよって方はしばしお待ちを。

 

 今回はこんなところで終わろうと思います。ご意見、ご質問等ありましたら、コメント欄の方へお願いします。Pythonアプリ開発日記(今名付けた)の方も少しずつ進んではいるのであまり期待せずお待ちいただければ幸いです。ではでは~。

環境構築

 今まではなんとなくでプログラムを書いていたんですが、今後アプリケーション開発に手を出すことになるので、しっかりと環境を組んでいきたいと思います。

 今回やっていくのはvirtualenvによるpython仮想環境の用意になります。

 

注意として、今回はWindows10で環境を構築しています。LinuxMac等別のOSで作業をしている方は別の方法が必要になりますのでご注意ください。

 

1.virtualenv(venv)の準備

 さて、一つ目は仮想環境の準備です。仮想環境とは何ぞやって感じではあるのですが、簡単に言うとコンピューターの内部で仮想的に実行環境を整えるもので、よくモジュールなどを案件ごとに管理するために使います。pythonで使える仮想環境としてはpipenv等他にもあるのですが、今回はvirtualenvを使用していきます。

 

 pythonは導入されているものとして話を進めますので、まだ導入していない方は以下のリンクからダウンロード、インストールをしてください。

Download Python | Python.org

 

 ここからは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!と表示するものを用意します。

test.py

 作成したフォルダに移動し、

python <プログラム名>.py 

で実行してみてください。以下の画像のように出力されれば成功になります。

プログラムを入れた後のフォルダ内容と実行結果

 実際の使い方としてはこのように仮想環境を起動している段階でpip等でモジュールをインストールすると、他のフォルダに影響を及ぼすことなくインストールすることが可能になります。

 

4.閉じ方
 最後に仮想環境の閉じ方です。

 deactivate

こちらのコマンドで仮想環境を閉じることができます。

閉じた結果

 

5.二回目以降

 二回目以降は上に書いたことを全てする必要はありません。起動すること、そして閉じることの二つのみでOKです。

 起動するとき

   開きたいフォルダの入っているフォルダ(今回の場合はC:\Users\chach\python)で

 <フォルダ名>\Scripts\activate.ps1

    のコマンドを実行してください。

 閉じるとき

   仮想環境に入っている状態で

 deactivate

    のコマンドを実行してください。

 

6.終わりに

 今回はwindows環境下でpythonを仮想環境virtualenvで開発していく方法をまとめていきました。少しでも参考になれば幸いです。

 

 

ご挨拶

はじめまして、情報系の大学に通っているchachaと申します。

pythonの勉強を独学で行っており、その中で先人達のブログにお世話になりました。学んだものを纏めておき、またインターネットに学んだものを少しでも還元したいと思い、このブログをはじめました。

初めての投稿ですのでミスなども起こりうるでしょうが、温かい目でお応援いただければ幸いです。

 

さて、今後の目標なのですが、11月に発売されるポケモンSVの対戦支援ツールの開発の開発を目指していきたいと思っています。どういった内容になるかはわかりませんが、GUISQLなど様々なものを利用していく予定です。どこまでできるかわかりませんが、応援よろしくお願いいたします。