もっとpy

Table of Contents

python venv

OpenBSDにはデフォでvenvが導入されていない。必要な人は自分で、 py3-virtualenv を入れて下さいって態度。

vbox$ python -m venv --upgrade-deps mypy
Requirement already satisfied: pip in ./mypy/lib/python3.9/site-packages (22.0.4)
Collecting pip
  Downloading pip-23.0-py3-none-any.whl (2.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 5.3 MB/s eta 0:00:00
Requirement already satisfied: setuptools in ./mypy/lib/python3.9/site-packages (58.1.0)
Collecting setuptools
  Downloading setuptools-67.2.0-py3-none-any.whl (1.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 5.4 MB/s eta 0:00:00
Installing collected packages: setuptools, pip
  Attempting uninstall: setuptools
    Found existing installation: setuptools 58.1.0
    Uninstalling setuptools-58.1.0:
      Successfully uninstalled setuptools-58.1.0
  Attempting uninstall: pip
    Found existing installation: pip 22.0.4
    Uninstalling pip-22.0.4:
      Successfully uninstalled pip-22.0.4
Successfully installed pip-23.0 setuptools-67.2.0

元々ある古いパッケージを削除して、最先端な奴に置き換えている。

vbox$ tree .cache/pip/http/
.cache/pip/http/
|-- 0
|   `-- 4
|       `-- 1
|           `-- 8
|               `-- c
|                   `-- 0418c83b80f7f7bfaec2738bfbbee53d2c1562196c0781702f6eddc8
20 directories, 4 files

ダウンロードされた物は、こんな場所に分散して格納されてた。データ自身は ウェブからのレスポンスを、そのままログしてるみたいだ。それにしても、随 分と分散させてる。いやみな格納場所だな。

vbox$ cat .cache/pip/selfcheck/4f19fbddd587f7b07b75fa60....
{"key":"/tmp/mypy","last_check":"2023-02-12T22:36:02Z","pypi_version":"23.0"}

その他に、チェック・ログも保存してた。

vbox$ du -sh .cache/pip /tmp/mypy/
3.2M    .cache/pip
17.2M   /tmp/mypy/

気分良く拡張してくと、当然ながら肥大する。その程度を、この例から想像し ておこう。

MSYS2 だと ~/AppData/Local/pip/cache/ が、置き場所になる。

python trace

pythonはLispを凌駕したくて、デフォでtraceってモジュールが用意されてる。

vbox$ python -m trace --help
  :
Filters:
  Can be specified multiple times

  --ignore-module IGNORE_MODULE
                        Ignore the given module(s) and its submodules (if it
                        is a package). Accepts comma separated list of module
                        names.

モジュールにもヘルプが用意されてるのね。

(mypy) vbox$ python -m trace  --trace --module pip check

こんな事をやると膨大なログが出てくる。

fgrep -- '--- modulename:' LOG2

こんな事をやりながら、五月蝿いモジュールを洗いだして、無効なリストに登 録してく。

python -m trace --trace --ignore-module _bootstrap,_bootstrap_external,sre_parse,sre_compile --module pip check >LOG3

その結果がこうだ。本当にとんでもないログになる。

wc LOG*
 2941347 14120296 165867069 LOG
 2921083 13829293 161415337 LOG1
 2896433 13444919 154007037 LOG2
 2037987 9611034 111181909 LOG3

トレースしたいモジュールを指定できるオプションも付けて欲しいぞ。

python pdb

この不満、ひょっとしたらpython用のデバッガーである、pdbで解決できない か?

(mypy) ob$ python -m pdb -m pip check
> /tmp/mypy/lib/python3.9/site-packages/pip/__main__.py(1)<module>()
-> import os
(Pdb) b pip/_internal/cache.py:29
Breakpoint 1 at /tmp/mypy/lib/python3.9/site-packages/pip/_internal/cache.py:29
(Pdb) c
No broken requirements found.
The program exited via sys.exit(). Exit status: 0
> /tmp/mypy/lib/python3.9/site-packages/pip/__main__.py(1)<module>()
-> import os

ここに飛んで来るだろと思ったら外れた。勘はいかんぜよ。心を入れ替えて、 まともな所にBPを置いてみる。

(Pdb) b pip/_internal/commands/check.py:25
Breakpoint 1 at /tmp/mypy/lib/python3.9/site-packages/pip/_internal/commands/check.py:25
(Pdb) c
 :
(Pdb) bt
  /usr/local/lib/python3.9/bdb.py(580)run()
-> exec(cmd, globals, locals)
  /tmp/mypy/lib/python3.9/site-packages/pip/__main__.py(31)<module>()
-> sys.exit(_main())
  /tmp/mypy/lib/python3.9/site-packages/pip/_internal/cli/main.py(70)main()
-> return command.main(cmd_args)
  /tmp/mypy/lib/python3.9/site-packages/pip/_internal/cli/base_command.py(101)main()
-> return self._main(args)
  /tmp/mypy/lib/python3.9/site-packages/pip/_internal/cli/base_command.py(214)_main()
-> return run(options, args)
  /tmp/mypy/lib/python3.9/site-packages/pip/_internal/cli/base_command.py(160)exc_logging_wrapper()
-> status = run_func(*args)
> /tmp/mypy/lib/python3.9/site-packages/pip/_internal/commands/check.py(25)run()
-> missing, conflicting = check_package_set(package_set)

今度は上手くヒットした。スタックの表示が普通のやつと逆になってるな。人 間の心理として、注目してるのを先に表示してほしい。何時もbdb.pyのコード をみせられるのは、いやだ。

でも、こういう表示順だと、フレームのup/downが、見たままの素直さなんだ よな。でも、そんなのは素人さん好みの事だろう。まあ、pythonは万人向けに 設計されてますから、かな? フレームを幾つ表示させるかのオプションは必 須と思うけど、どうよ。

(Pdb) l
 20           %prog [options]"""
 21
 22         def run(self, options: Values, args: List[str]) -> int:
 23
 24             package_set, parsing_probs = create_package_set_from_installed()
 25 B->         missing, conflicting = check_package_set(package_set)
 26
 27             for project_name in missing:
 28                 version = package_set[project_name].version
 29                 for dependency in missing[project_name]:
 30                     write_output(
(Pdb) pp package_set
{'asttokens': PackageDetails(version=<Version('2.2.1')>, dependencies=[Requireme
nt.parse('six')]),
 'backcall': PackageDetails(version=<Version('0.2.0')>, dependencies=[]),
   :

こんなデータから、矛盾を探すのか。どんな風にやってる? ステップしてみ る。

(Pdb) s
--Call--
> /tmp/mypy/lib/python3.9/site-packages/pip/_internal/operations/check.py(51)check_package_set()
-> def check_package_set(
(Pdb) s
> /tmp/mypy/lib/python3.9/site-packages/pip/_internal/operations/check.py(60)check_package_set()
-> missing = {}

あれ、中へは潜り込まないの? emacsから起動すると、ソースを表示してくれ るので、今は何処ってのが欲わかる。上記は誤解であった。スマソ。

emacsからだと、こんな風に起動する。

M-x pdb
Run pdb (like this): python -m pdb -m pip check
(Pdb) b pip/_internal/commands/check.py:run
 *** Bad lineno: run
(Pdb) b pip/_internal/commands/check.py:25
Breakpoint 1 at /tmp/mypy/lib/python3.9/site-packages/pip/_internal/commands/check.py:25

BPの設定は名前では出来なくて、行番号が要求される。少し追跡、コードが表 示されるのはありがたい。

    for package_name, package_detail in package_set.items():
        # Info about dependencies of package_name
=>      missing_deps: Set[Missing] = set()
        conflicting_deps: Set[Conflicting] = set()

これって、集合演算してるのかな。まあ、そんな事だろう。それよりemacsの 楽しい機能に気付いてしまった。

BPを貼る時に、別な端末でcheck.pyを開いていたんだ。コマンドっていうdir の中のやつね。pipのコマンドだろうって言う推測ね。上のソースのemacsのス テータス・ラインには、 check.py<operations> と表示されたぞ。いわ ゆる下請けのエリアをめざとく見つけてくれたって事。なかなかヤルナ。

site-packages/pip-23.0.dist-info/entry_points.txt

[console_scripts]
pip = pip._internal.cli.main:main
pip3 = pip._internal.cli.main:main
pip3.9 = pip._internal.cli.main:main

今度からは、ここから辿って行こう。それぞれのパッケージに付属してるよ。

待て、いつものデバッガーを取り出す前にetagsはどうだ。MSYS2にはemacsを 入れないと、はいってこない。機転をきかせてユニバーサルなctagsを入れて みる事にする。

sakae@atom MINGW64 /r/pip
$ ctags -e `find . -name '*.py'`

こんな風に -e を付けるとemacs用のTAGSを作ってくれる。後はいつも通りだ。 pythonは指導が良いせいか、関数名が説明的な名前になってるんで、スラスラ と読めるな。pythonと馬鹿にしてたけど、素直に記述してあって読み易い。

python numba

pythonを高速化する方法って色々あったと思うんで調べてみた。

Python の高速化 なる程、 Numba というのが良さそうだ。試してみる。

from numba import jit
import time

def func_speed(func):
    def _wrapper(*args, **keywargs):
        start_time = time.time()
        result = func(*args, **keywargs)
        print('time: {:.9f} [sec]'.format(time.time() - start_time))
        return result
    return _wrapper

@jit
def fib(n):
    if n < 2:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

@func_speed
def meas(n):
    return fib(n)

meas(35)

デコレータである @jit の有無による、実行時間の差。最初の2つは、無しの 状態。次にイネーブルした。

time: 9.260488749 [sec]
9227465
>>>
time: 9.245790243 [sec]
9227465
>>>
This decorator is used to compile a Python function into native code.
>>>
time: 0.616049767 [sec]
9227465
>>>
time: 0.625315189 [sec]
9227465

python decorator

上で出てきたデコレーターってやつは、Lispで言うマクロではなかろうか? ちょいと調べてみるか。

Pythonのデコレータについて

Pythonのデコレータを理解するまで

違ったわい。マクロ以下だった。検索して出てくるのは、VB系のやつだった。 難しい事は出来なくなってるんだな。

最近知ったんだけど、こんなマクロ展開というか、文字列の中で、変数の展開 ができるんだね。shell,ruby,gaucheとかでは、とっくの昔にサポートされて た。

>>> a = 'Hello'
>>> b = 'world'
>>> f'{a}, {b}'
'Hello, world'

折角なのでnumbaのデコレータを見学してみる。普通な人は立ち入る事がない エリアだ。FreeBSDでインストール後の結果を見ようとしたら、コンパイルが 初まってしまったので、ソースをいきなり見学。 numba 0.56.4

/tmp/numba-0.56.4/numba/tests/test_npdatetime.py
274:     def jit(
581:     def jit(
/tmp/numba-0.56.4/numba/core/decorators.py
=>: def jit(
/tmp/numba-0.56.4/numba/cuda/decorators.py
14: def jit(
/tmp/numba-0.56.4/numba/cuda/simulator/api.py
78: def jit(

cudaって、採掘用のハードかな。パワーユーザー用で、庶民には関係ない。 普通のjitを見学。

def jit(signature_or_function=None, locals={}, cache=False,
        pipeline_class=None, boundscheck=None, **options):

    Examples
    --------
    1) jit(signatures, **targetoptions) -> jit(function)
            @jit("int32(int32, int32)")
            def foo(x, y):
                return x + y
    2) jit(function, **targetoptions) -> dispatcher
            @jit
            def foo(x, y):
                return x + y

こんな具合に、説明が充実してる。本文は読ななくてもいい気分になるぞ。

python polars

python idle

sakae@atom MINGW64 ~
$ which idle
/mingw64/bin/idle
What GUI toolkits exist for Python?
===================================

Standard builds of Python include an object-oriented interface to the Tcl/Tk
widget set, called :ref:`tkinter <Tkinter>`.  This is probably the easiest to
install (since it comes included with most
`binary distributions <https://www.python.org/downloads/>`_ of Python) and use.
For more info about Tk, including pointers to the source, see the
`Tcl/Tk home page <https://www.tcl.tk>`_.  Tcl/Tk is fully portable to the
macOS, Windows, and Unix platforms.

python 3.11.2

Python 3.11.2 が、2月の8日にでたというので、お試し。

time ./configure –enable-shared で、49秒。コンパイルに

real    5m59.162s
user    5m35.768s
sys     0m15.318s

あっ、-j2 するの忘れていた。これ、ArchLinux/VirtualBoxなんで、VMWAREの 時は忘れないようにしよう。

バージョンによる違いを確認。前の方に出てきた、fib(35)。だって、再帰を 頑張って最適化したそうなので。。

[sakae@arch tmp]$ python -V
Python 3.10.9
[sakae@arch tmp]$ python fib.py
time: 9.199959278 [sec]
[sakae@arch tmp]$ python3 -V
Python 3.11.2
[sakae@arch tmp]$ python3 fib.py
time: 6.330782652 [sec]

何もせずとも、速くなった。numbaは数値計算専用のjitだけど、新しいpython は、あまねく薄く効果を発揮するのね。

numbaの守備範囲は、どうした訳か狭いんです。

    raise RuntimeError(msg.format(cur_py, min_py, max_py))
RuntimeError: Cannot install on Python version 3.11.2;
only versions >=3.7,<3.11 are supported.

こういう事が他にないか? 各種のパッケージが対応してるかだなあ。常にこの事を頭にいれておな ねば、ならない。走り続ける事が、Zen of Python ですから。

etc