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の実例版。
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"])