tkinter

try RubiksCube-TwophaseSolver

前回archでやったルービック・キューブの解決方法の資産をOpenBSDに移動させてやってみる。OpenBSDは訳あって非力な環境にしてる。でも、頭脳をもってくれば、バンバン動くはず。

近頃のAIは、ググル様のGPUパワーが有り余ってる所で、頭脳を鍛え、それを公開するって風潮だから、今回の例はそれに習うな。

ニューラル機械翻訳(NMT)の基礎を「JoeyNMT」で学んでみよう(準備編) ここで言う学習済みモデルだな。

vbox$ python3.9  example.py
loading conj_twist table...
loading conj_ud_edges table...
loading flipslice sym-tables...
loading corner sym-tables...
loading move_twist table...
loading move_flip table...
loading move_slice_sorted table...
loading move_u_edges table...
loading move_d_edges table...
loading move_ud_edges table...
loading move_corners table...
loading phase1_prun table...
loading phase2_prun table...
loading phase2_cornsliceprun table...
loading phase2_edgemerge table...
Server socket created
Traceback (most recent call last):
Server now listening...
  File "/tmp/RubiksCube-TwophaseSolver/example.py", line 59, in <module>
    import client_gui
  File "/tmp/RubiksCube-TwophaseSolver/client_gui.py", line 3, in <module>
    from tkinter import *
ModuleNotFoundError: No module named 'tkinter'

pythonのTcl/Tkバインディングが必要とな。 pkg_add python-tkinter-3.9.12.tgz で、さくっと導入。

arch linuxの時は起動したら、libtk8.6.soが無いってエラッたんで、tk入れたよ。それぞれのOSによって、エラーの出方はまちまちなのね。

easy see

サーバーとのやり取り文字が醜いので、人間に優しくしてみた。solve関数の中ね。 client_gui.py

import re

#    show_text(defstr)
    show_text(re.split('(.........)', defstr)[1::2])
    try:
        s.sendall((defstr+'\n').encode())
['DRLFUURDD', 'RBFURLLBB', 'FFBDFLDLU', 'FDBRDLDRU', 'BUURLBFDR', 'UFLFBURBL']
DRLFUURDDRBFURLLBBFFBDFLDLUFDBRDLDRUBUURLBFDRUFLFBURBL
L3 B1 U2 F3 B1 D2 B2 U1 D1 F1 D3 B2 R2 F3 D2 B1 D2 B2 (18f)

['UUUUUUUUU', 'RRRRRRRRR', 'FFFFFFFFF', 'DDDDDDDDD', 'LLLLLLLLL', 'BBBBBBBBB']
UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB
(0f)

18手数で解決しましたとな。次は既に完成している場合だ。凄いな。

凄いと言うなら、re.splitの部分も褒めてあげて下さい。こんなのオイラーには解決出来無いですよ。さすが世の中の人が、こぞって使うpythonだけあるな。ググレば直に解決方法が出て来る。

種あかしは、スライスの指定にある。開始位置と終了位置を[開始位置:終了位置]で使う方法と、次のように、スライスを増分で指定する方法だ。 [開始位置:終了位置:増分] 。今回は、後者の指定方法で、終了位置を省いたものだ。勿論、開始位置はZERO番から始まる。

tkinter

tkinter — Tcl/Tk の Python インターフェース 本家の資料

PythonのTkinterを使ってみる 易しい入門

Tkinterの使い方:Canvasクラスで描画した図形を操作する 専門的ってか、ゲームのアプリまで解説されてる、充実したサイト

このtkinterを使って、美しい画面が作成される。こんなに綺麗だったっけ? 昔の無骨なTkを知ってる身としては、信じられない。まて、騙されるな。カラフルな色で盛ってるから綺麗に見えるだけだろう。丁度、インスタ映えするように盛った写真を上げるようなものか。

help and pydoc3

>>> help('tkinter')
Help on package tkinter:

NAME
    tkinter - Wrapper functions for Tcl/Tk.

MODULE REFERENCE
    https://docs.python.org/3.10/library/tkinter.html
     :
    Example (Hello, World):
    import tkinter
    from tkinter.constants import *
    tk = tkinter.Tk()
    frame = tkinter.Frame(tk, relief=RIDGE, borderwidth=2)
    frame.pack(fill=BOTH,expand=1)
    label = tkinter.Label(frame, text="Hello, World")
    label.pack(fill=X, expand=1)
    button = tkinter.Button(frame,text="Exit",command=tk.destroy)
    button.pack(side=BOTTOM)
    tk.mainloop()

helpすると膨大なドキュメントが出て来る。お目当てな単語を検索すればよい。裏でless相当が動いているんで、/Buttonとかすればよい。申し訳程度に、例が出て来た。

server> pydoc3 -b
Server commands: [b]rowser, [q]uit
server> b
 :
Python 3.9.13 [main, Clang 13.0.0 ]
OpenBSD-7.1
Module Index : Topics : Keywords
[               ] [Get]

[               ] [Search]


Index of Modules


Built-in Modules
         _abc              _operator         _tracemalloc      itertools
         _ast              _peg_parser       _warnings         marshal
         _codecs           _signal           _weakref          posix
         _collections      _sre              atexit            pwd
         _functools        _stat             builtins          sys
         _imp              _string           errno             time
         _io               _symtable         faulthandler      xxsubtype
         _locale           _thread           gc

w3mが起動して、後は、検索するなり、好きにしろとな。

pdb

python用のデバッガーを使ってみる。単独で動くように、#import cubie のごとくキューブ関係を読み込まないようにしておくのが吉。これで、tkinterの巨大なアプリになる。

[sakae@arch tmp]$ python3.10 -m pdb client_gui.py
> /tmp/client_gui.py(3)<module>()
-> from tkinter import *
(Pdb) b empty
Breakpoint 1 at /tmp/client_gui.py:120
(Pdb) c
> /tmp/client_gui.py(122)empty()
-> for f in range(6):
(Pdb) l
117                     canvas.itemconfig(facelet_id[f][row][col], fill=canvas.itemcget(facelet_id[f][1][1], "fill"))
118
119
120 B   def empty():
121         """Remove the facelet colors except the center facelets colors."""
122  ->     for f in range(6):
123             for row in range(3):
124                 for col in range(3):
125                     if row != 1 or col != 1:
126                         canvas.itemconfig(facelet_id[f][row][col], fill="grey")
127
(Pdb) c
> /tmp/client_gui.py(122)empty()
-> for f in range(6):
(Pdb) c
> /tmp/client_gui.py(122)empty()
-> for f in range(6):
(Pdb) pp facelet_id
[[[9, 10, 11], [12, 13, 15], [16, 17, 18]],
 [[19, 20, 21], [22, 23, 25], [26, 27, 28]],
 [[29, 30, 31], [32, 33, 35], [36, 37, 38]],
 [[39, 40, 41], [42, 43, 45], [46, 47, 48]],
 [[49, 50, 51], [52, 53, 55], [56, 57, 58]],
 [[59, 60, 61], [62, 63, 65], [66, 67, 68]]]

emptyにBPをおいてから実行。後はボタンを押すとpdbに制御が移る。適当にpdbの操作をすればよい。

emacsからだど、M-x pdb すればよい。python3を指定する亊。

Run pdb (like this): python3 -m pdb client_gui.py
;; python
(setq python-shell-interpreter "python3")

は効かないのかな?

progmodes/gud.el.gzを見る限り、決め打ちだなあ。それとも、カスタムってなってるから、カスタム化しろって亊かな。いい加減、python = python3 にしちゃうのが吉かな。

(defcustom gud-pdb-command-name
  (if (executable-find "pdb") "pdb" "python -m pdb")
  "Command that executes the Python debugger."
  :version "27.1"
  :type 'string
  :group 'gud)

なんてったってアイドル

小泉今日子 / なんてったってアイドル (1985-11) じゃ、おじさん過ぎる。 それに、英語だと、idol が、アイドルの綴だ。日本語耳、丸出しで恥しいぞ。

ここは、idle/pythonです。tkinterの実例版。

Python入門(1) IDLEを使う

Python の IDLE の使い方

PythonのIDLEでデバッグを行う方法

OpenBSDなら、python-idle-3.9.13を入れるだけ。起動は、idle3若しくは

ob$ cat idle3.9
#!/usr/local/bin/python3.9

from idlelib.pyshell import main
if __name__ == '__main__':
    main()

もういいかげん、python2とは縁がキレているんだから、普通にpythonとかidleでいいと思うんだけど、どうよ。で、アイドル軍団は、/usr/local/lib/python3.9の下に鎮座するidlelib群だ。この中の、pyshell.pyファイルにおわすmainがエントリーポイントとな。

今更、何を血迷ってGUIか? そんなにpythonをやる気がないのに、重厚なipythonを入れる気がしない。ちょうどtkinterに目をつけたんで、その実例を見るのにうってつけって亊です。

おまけで、亀さんグラフィックがHelpメニューにあった。これも見所満載の感じがする。

mainmenu.pyに、

if find_spec('turtledemo'):
    menudefs[-1][1].append(('Turtle Demo', '<<open-turtle-demo>>'))

こんな設定になってたんで、デモを探したよ。そしたら、/usr/local/lib/python3.9/turtledemoに

ob$ wc *py
      14      34     314 __init__.py
     398    1353   15050 __main__.py
     161     392    4248 bytedesign.py
      59     115     951 chaos.py
     132     270    3201 clock.py
      58     100    1339 colormixer.py
     108     321    2966 forest.py
     138     413    3473 fractalcurves.py
     119     248    2434 lindenmayer.py
      79     229    2051 minimal_hanoi.py
     226     621    6513 nim.py
      54     133    1291 paint.py
      61      97    1066 peace.py
     175     388    3380 penrose.py
     111     270    2825 planet_and_moon.py
      65     166    1361 rosette.py
      86     216    1804 round_dance.py
     204     525    5052 sorting_animate.py
      62     179    1401 tree.py
      54     131    1119 two_canvases.py
      49      76     821 yinyang.py
    2413    6277   62660 total

適当なサイズのコード例が多数掲載されてた。お手軽なグラフィックだな。

pypy

ひょんな亊から、こんなのを見付た。名前は知ってたけど、python2系しかないと思っていたら、3系もあるのね。 PyPy Releases

普通のPythonにJITを組み込んだものらしい。スピードアップが期待出来る。但し制限があって、C言語で提供されるモジュールは使えないとの亊。ピュアなPythonを使っている限りでは、恩恵に与れるらしい。

Pythonで競プロをしよう!〜入門者が知っておくべきTips

再帰は遅いとな。

問題はpypy用のpipが有るかだな。pipを使ってインストールしましょって記事で、pip install hogeって記事をよく見るけど、これは間違いらしい。 正式な方法は、python -m pip install hoge だそうだ。今動いているpythonのバージョンに即した物をインストールする。混ぜるな危険が避けられる訳だ。

pypy -m pip が出来るなら、Welcome pypy だな。気になる亊は、直ぐにやる。

sakae@deb:~$ MINE/bin/pypy -V
Python 3.9.12 (05fbe3aa5b0845e6c37239768aa455451aa5faba, Mar 29 2022, 12:14:17)
[PyPy 7.3.9 with GCC 10.2.1 20210130 (Red Hat 10.2.1-11)]

これって、Python 3.9.12を土台にpypy 7.3.9を仕込みましたって亊だな。んで、pipが入っていなかったので、素材を取り寄せて、インストールしろとな

wget https://bootstrap.pypa.io/get-pip.py
MINE/bin/pypy get-pip.py

こんな風になった。勿論pipはそのまま使わない。

sakae@deb:~$ ls -l MINE/bin/pip*
-rwxr-xr-x 1 sakae sakae 230 Jul  7 14:09 MINE/bin/pip*
-rwxr-xr-x 1 sakae sakae 230 Jul  7 14:09 MINE/bin/pip3*
-rwxr-xr-x 1 sakae sakae 230 Jul  7 14:09 MINE/bin/pip3.10*
-rwxr-xr-x 1 sakae sakae 230 Jul  7 14:09 MINE/bin/pip3.9*

pypy -mpip numpy したよ。

sakae@deb:~$ MINE/bin/pypy
Python 3.9.12 (05fbe3aa5b0845e6c37239768aa455451aa5faba, Mar 29 2022, 12:14:17)
[PyPy 7.3.9 with GCC 10.2.1 20210130 (Red Hat 10.2.1-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>> import numpy

ウンウンとファンが唸って、どうやらインストール成功。後は、おいおいだな。

裸のTk

tkinterは、Tcl/TkのうちのTkへのアクセスをpythonから行うものだった。じゃ、裸のTkはどうなってる? 確かデモが有ったはず。探したら出て来た。 /usr/lib/tk/demos (at arch linux)

但し、debianには入っていない。こういう有用な資料を入れていないのは、残念な亊だ。まあ、WindowsのDeskTopの真似をひたすら追求してれば、プログラミングの亊が疎かになるのは、しょうがない。その点、arch linuxは、プログラミング大好き人間の御用達だな。

まずは、何がなくてももハロワだ。 hello って名前で登録されてる。

#!/bin/sh
# the next line restarts using wish \
exec wish8.6 "$0" ${1+"$@"}

package require Tk

button .hello -text "Hello, world" -command {
    puts stdout "Hello, world"; destroy .
}
pack .hello

グラフィックな部品を叩くためwishってコマンドを使う。何を隠そう、これはtclの亊だ。 なんか、面倒っぽい。だからpythonがtclの代わりを務めてTkを叩いてくれるのね。

圧巻は、widgetってアプリを起動して、それぞれのデモカテゴリーの中にある、アニメーションの最後のやつ。goldberg.tcl。

ピタゴラ・スイッチがでてくる。ステップ実行が出来たり、動作のブロック毎にポーズさせたり。まあ、楽しいよ。コードは大変で見る気がしないけど。

demoは何処だ?

archのtkdemosは、実に分かり易い場所にあった。それじゃOpenBSDは? /usr/local/share/examples/tk8.5/ にあった。入れた覚えがないんだけど、入ってた。ご主人様に忖度してるんだな。勿論idleのHELPメニューにも、亀さんデモって亊で、登場してくれている。

debianの場合は、多分、こうじゃなかろうか。今更ですけども。

sakae@pen:~$ apt-cache search tk8.6-doc
tk8.6-doc - Tk toolkit for Tcl and X11 v8.6 - manual pages

で、入れた物は、/usr/share/doc/tk8.6-doc/demos に有った。起動スクリプトは実行属性が付いていない。安全に忖度してんな。

sakae@pen:/usr/share/doc/tk8.6-doc/demos$ wish widget
-bash: wish: command not found
sakae@pen:/usr/share/doc/tk8.6-doc/demos$ wish8.6 widget

wishが無い時は、これまた想像してください、で、あるか。勿論、こんな変な場所に配置されてる一群をidleは忖度してくれないよ。亀さんデモもメニューは出てこない。

idle側でのモジュール検索は

importlib.util.find_spec = find_spec(name, package=None)
    Return the spec for the specified module.

    First, sys.modules is checked to see if the module was already imported. If
    so, then sys.modules[name].__spec__ is returned. If that happens to be
    set to None, then ValueError is raised. If the module is not in
    sys.modules, then sys.meta_path is searched for a suitable spec with the
    value of 'path' given to the finders. None is returned if no spec could
    be found.

    If the name is for submodule (contains a dot), the parent module is
    automatically imported.

    The name and package arguments work the same as importlib.import_module().
    In other words, relative module names (with leading dots) work.

モジュールの体裁を取っていないとダメなのか。面倒この上ない。待て、python系にもデモを用意しないといけないだろう。探してみたぞ。

sakae@pen:~$ sudo apt install python3.9-examples

そしたら、こんな名前で用意されてた。逆にこれから想像はつかないな。素人さん、お断りって匂がプンプンするぞ。デビアンは色々用意されてて便利って言うけど、探し当てるまで一苦労だな。ちなみに、検索方法の極意は、

sakae@pen:/usr/lib/python3.9$ apt-file search turtledemo

Gauche-tk

裸のTkもいいんだけど、何か衣を纏っていた方がよい。括弧がオイラーの趣味にあうぞ。探したら、 Gauche-tk なんてのが出てきた。リクエストが多かったのでさくっと作ってみましたですって。shiroさん凄い。

Gauche-Tkで簡単GUIプログラミング こちらの方もようやるわと、感心しますよ。

オイラーはヘタレなので、手抜きします。

ob$ cat bind.scm
;; binding event callback

(use tk)
(with-module tk (set! *tk-debug* #t))
(tk-init '())
(tk-bind "." '<Key>      (tklambda (%K) (print #"Pressed ~%K")))
(tk-bind "." '<Button-1> (tklambda (%x %y) (print #"Clicked at (~%x ~%y)")))
(tk-mainloop)

examplesにあったものに、debugを追加。ね、ヘタレでしょ。このアプリは、出て来た窓の中で、マウスクリックすると、その座標位置を報告してくれるものだ。

ob$ gosh bind.scm
> gauche__tk__do bind "." <Key> "gauche__tk__callback 1 %K"
< ok

> gauche__tk__do bind "." <Button-1> "gauche__tk__callback 2 %x %y"
< ok

! 2 41 35
Clicked at (41 35)
! 2 56 173
Clicked at (56 173)

gosh側のスクリプトをwishに送りつけて、そこで実行。結果をgoshに取り込んでいる。先のdebug行は、その流れをモニターするものだ。

目玉はパッケージの核になるtk.scmだ。goshのオブジェクトをtclに分るように変換してる。そして別プロセスで動くwishと通信するって戦略。

(define-tk-commands
  (tk-bell bell)
  (tk-bind bind)
  (tk-bindtags bindtags)
   :
  ;; Ttk widgets
  (ttk-button ttk::button)
  (ttk-checkbutton ttk:checkbutton)

こんな、あらましが搭載されてるので、見ておくと吉かな。

python + gnuplot

PythonからGnuplotを使ってグモウスキー・ミラの写像を作図する

from subprocess import call
call( ["gnuplot", "-e", "plot sin(x); pause -1"])

This year's Index

Home