WSLでtkinterとpyinstallerを動かすテスト
WSLでtkinterとpyinstallerを動かすテスト
※ 注意
WindowのWSLでUbuntuを入れ、そこでPythonを動かす環境向けの投稿。
PythonでGUI(グラフィカルなユーザー・インターフェース)アプリを作るライブラリは
Tkinter
Kivy
PyQt
wxPython
PySimpleGUI
Pygame
等いくつかあります。その中でもTkinter
はPythonに標準装備されています。
今回おこなうこと
Tkinter
がWSLのUbuntuで動くかかどうか試します。Tkinter
で作ったpyファイルをpyinstaller
でexeファイル
に変換し、動作確認します。
LinuxでGUIを動かすにはX Window System
とかX server
とか呼ばれるものをインストールしなければなりません。それと、GUIのテキストボックスに日本語入力するような場合はLinuxの日本語入力設定も必要です。のちほど。
【実行環境】
- Windows10 Home
- WSL:Ubuntu:Anaconda
- Python3.8
目次
先に結論を申し上げますと
上の3つについて、
- WSLのLinuxに入れたAnacondaのPythonで
tkinterアプリ
を作成し、WSLで実行することができた(GUIが起動した)。
自分の環境ではWindows側にPythonを入れていないので、WSLを起動させないとpyファイルは動かせない。 pyinstaller
は「pyファイル
をスタンドアローン型のEXE実行ファイル
に変換するライブラリ」 です。結果的に 実行ファイルは動かすことが出来た。 が、条件がある。
検索すると、stackoverflowなどのサイトでは「Wine Linux
では実行ファイルが作れるが、Debian Linux
では無理げ」とか、「実行ファイルには変換できたが動かない」など実行環境でマチマチのようです。
また、「全てのpythonライブラリに対応している訳ではない」ようなことが公式ドキュメントに書いてあります。対応ライブラリを表にしてあるが、tkinter
は載っていない。(DjangoやmatplotlibなどはEXEファイルに出来る。)。載ってないが今回のは動いた。- 「pyinstallerはクロスコンパイラではない」ともある。Windowで作ったpyファイルはWindowで動く実行ファイルにしか変換できない、Linuxで作ったものはLinuxでしか動かない、その他のOSも同様。という意味だそうです。
よって、WSLのLinuxOS上のpythonで作ったpyファイルをpyinstallerで実行ファイルに変換できたとしても、Windowのエクスプローラでクリックしても動かない。動かすにはLinuxから実行する以外ない。
以上。
ここから以降は、実際にtkinter
でアプリ作成と実行テスト、pyinstaller
での実行ファイル作成作業に移っていきます。
UbuntuでGUIを動かす + 日本語入力できるようにする
WSLでLinuxを入れたからと言って、ハードディスクをパーティションで別けてブートローダーでOSを切り替える時のように見た目がゴロッと変わるわけでもなく、普通にWindowsで、何が動いているのか分かりにくい。
VSCodeもJupyterNotebookも、巷にあふれる「WSLでPythonを動かす設定方法」に従ってインストールいれば普通に日本語入力できるし・・・GUIの設定って言うが、VSCodeもJupyterもGUIで動かしてるし・・・
何か他に設定しなくちゃいけないの?
しなくちゃいけないみたいです。
自分の環境では、X server
は設定が済んでいたのでtkinterでGUIが表示されたものの、GUIのテキストボックスに日本語入力ができなかった。
とりあえず、それらの設定方法は後回しに、次へ進む。
X server の起動
windowsのスタート ⇒ VcXsrv ⇒ XLaunch(またはデスクトップ上のアイコン) をクリック。
XLaunchのダイアログが起動する ⇒ 全てデフォルトで「次」をクリック。
画面右下のタスクバーの「∧
」のアイコンを押すと先ほどクリックしたXLaunch
のアイコンが追加されているのが確認できる。(バツ印でXみたいなヤツ)
この段階でXLaunchのアイコンがないとか、X Serverの設定が済んでいない場合は
【Windows 10】WSLでGUIアプリを動かす方法と日本語入力設定方法【VcXsrv】 - あんりふ! などを参考に。
tkinterの動作確認
さて、tkinterはGUIライブラリの「Tcl/Tk」を利用している。これはtkinterと同様にPythonに最初から付属と。次のコマンドをターミナルで実行すると、「Tcl/Tk」のダイアログが起動する。
$ python -m tkinter
閉じるには「QUIT」か「×」ボタン。
「Tcl/Tk」のダイアログが起動すれば、GUIもtkinterも利用可能な状態ということが確認できたっちゅうことで、出来なかったら前の工程に戻ってX server
の設定を確認のこと。
できたとして、次にいきます。早速GUIアプリを作成してみます。
ただダイアログが起動するだけのアプリ作成
pyファイルを作って、そのあとファイルをコマンド実行します。
(↓はJupyterのマジックコマンドの%%writefile
でファイル作成しております)
%%writefile hello_tk.py import tkinter as tk # ウィンドウを作成 win = tk.Tk() win.title("こんにちは、世界!") win.geometry('400x300') # 400x300 のxは小文字のエックス # ウィンドウを動かす win.mainloop()
Overwriting hello_tk.py
$ python hello_tk.py
タイトルしかないウィンドウが起動した。
テキストボックス アプリ作成
テキスト入力に応じて何か返すアプリを作る。
%%writefile tkinter_gui.py import tkinter as tk from tkinter import messagebox as mbox # ウィンドウを作成 win = tk.Tk() win.geometry('500x250') # 部品を作成 # ラベルを作成 label = tk.Label(win, text="お名前は?") label.pack() # テキストボックスを作成 text = tk.Entry(win) text.pack() text.insert(tk.END, 'なにがし') # OKボタンを押したとき def ok_click(): # テキストボックスの内容を得る s = text.get() # ダイアログを表示 mbox.showinfo('挨拶', s + 'さん、こんにちは!') # ボタンを作成 okButton = tk.Button(win, text='OK', command=ok_click) okButton.pack() # ウィンドウを動かす win.mainloop()
Overwriting tkinter_gui.py
$ python tkinter_gui.py
日本語入力できない・・ので設定
上のテキストボックスに日本語入力ができなかった。
Linuxの日本語入力設定をしていないから。mozc
とか入力メソッドを入れなきゃならんようです。
参考リンク(上に貼り付けたのと同じ)
【Windows 10】WSLでGUIアプリを動かす方法と日本語入力設定方法【VcXsrv】 - あんりふ! などを参考に行いました。
設定後、fcitx-mozc
での入力切替をできるようにするためにはターミナルで
$ fcitx-autostart # ← コマンド Fcitx is running correctly. # ← 出力
とコマンドする。
tkinterで出たGUIに日本語入力する場合は、「Ctrl+Space」を押すと入力メソッドが「Mozc」に変わる。
戻す時は再び「Ctrl+Space」(アルファベットしか入力できなくなる)。
fcitx-mozcの入力設定を行うには
$ fcitx-config-gtk3
をコマンドする。GUIのダイアログが起動し設定できる。
だが、「入力メソッド」で追加ボタン「+」を押してもmozc
も何も候補が出てこない・・・。
設定後に実行。
とりあえず日本語入力できたのでfcitx-mozcの設定云々は放置する。
tkinterで使えるフォントを確認する
%%writefile tkinter_font_families.py import tkinter as tk import tkinter.font win = tk.Tk() print(tkinter.font.families())
Writing tkinter_font_families.py
# (Jupyterで確認しています)
!python tkinter_font_families.py
('estrangelo midyat', 'clearlyu devangari extra', 'utopia', 'clearlyu arabic', 'luxi serif', 'cursor', 'clearlyu arabic extra', 'fixed', 'estrangelo nisibin', 'lucidatypewriter', 'courier 10 pitch', 'open look glyph', 'estrangelo talada', 'serto urhoy', 'bitstream charter', 'terminus', 'clearlyu pua', 'serto mardin', 'estrangelo edessa', 'clean', 'terminal', 'serto jerusalem', 'gothic', 'new century schoolbook', 'luxi sans', 'bitstream vera sans mono', 'clearlyu alternate glyphs', 'lucidabright', 'bitstream vera serif', 'estrangelo antioch', 'song ti', 'estrangelo quenneshrin', 'open look cursor', 'serto malankara', 'helvetica', 'mincho', 'estrangelo nisibin outline', 'clearlyu', 'east syriac adiabene', 'serto batnan', 'courier', 'lucida', 'clearlyu devanagari', 'nil', 'goha tibeb zemen', 'serto kharput', 'estrangelo turabdin', 'fangsong ti', 'charter', 'times', 'luxi mono', 'newspaper', 'serto jerusalem outline', 'clearlyu ligature', 'east syriac ctesiphon', 'proof', 'symbol', 'bitstream vera sans')
ここからはpyファイルをexeファイルに変換する作業に移ります。
pyinstallerで py ⇒ exe
pyファイルをスタンドアローンな実行ファイル(EXEファイル)にする為のライブラリをインストールします。
これを使うことにより、PythonがインストールされていないPCでもexeファイルを実行できるようになる。
WSLでLinuxを起動しなくとも、Pythonで作ったプログラムが動かせるようになるはず!
pyinstallerのインストール
インストールします。
- pipの場合は
$ pip install pyinstaller
- condaの場合は
$ conda install -c conda-forge pyinstaller
以下、出力
Collecting package metadata (current_repodata.json): done Solving environment: done ## Package Plan ## environment location: /home/user/anaconda3 added / updated specs: - pyinstaller The following packages will be downloaded: package | build ---------------------------|----------------- altgraph-0.17 | pyhd8ed1ab_0 21 KB conda-forge macholib-1.14 | pyh9f0ad1d_1 34 KB conda-forge pyinstaller-4.3 | py38ha8cb210_0 1.5 MB conda-forge pyinstaller-hooks-contrib-2021.2| pyhd8ed1ab_0 73 KB conda-forge ------------------------------------------------------------ Total: 1.6 MB
この4つをインストールするがよかですか?「y/n」みたいなことを聞かれたので「y」でよかですEnterした。
pyinstallerコマンドで py ⇒ exe
exeファイル化したいpyファイルを用意します。先ほど作ったテキストボックス付きの「tkinter_gui.py」というファイルをexeファイルにしてみます。
%ls | grep tkinter_gui.py
tkinter_gui.py*
pyファイルはカレントディレクトリにある。OK。
# pyinstallerでpyファイルを一つのexeファイルに変換する !pyinstaller tkinter_gui.py --onefile
以下、出力
14272 INFO: PyInstaller: 4.3 14273 INFO: Python: 3.8.10 (conda) 14386 INFO: Platform: Linux-4.4.0-19041-Microsoft-x86_64-with-glibc2.17 (中略) 100555 INFO: Building EXE from EXE-00.toc completed successfully.
どうやら成功した模様。2分ほどかかった。
%ls
Untitled.ipynb* build/ hello_tk.py* tkinter_gui.py*
__pycache__/ dist/ tkinter_font_families.py* tkinter_gui.spec*
build/
とdist/
の2つのフォルダ、そしてtkinter_gui.spec*
が新規作成された。
再び、
$ pyinstaller tkinter_gui.spec*
をするとexeファイルが出来るようだ。
$ pyinstaller tkinter_gui.spec
以下、出力
2553 INFO: PyInstaller: 4.3 2553 INFO: Python: 3.8.10 (conda) 2620 INFO: Platform: Linux-4.4.0-19041-Microsoft-x86_64-with-glibc2.17 (中略) 66269 INFO: Building EXE from EXE-00.toc completed successfully.
どうやら出来上がった。
出来たexeファイルはdist/
の中に入っているとか。
%ls ./dist
tkinter_gui*
拡張子がない。
出来た実行ファイルを動かすには
ここまで、WSLのUbuntu上に入れたAnacondaで作成したpyファイルを、pyinstallerで実行形式のバイナリファイルに変換した。実行ファイルは作業ディレクトリ内に自動作成されたdist/
ディレクトリへ保存された。
で、これをWindowsで動かそうとするのだが、一番最初に書いた結論の通り、「pyinstallerはクロスコンパイラではない」ので、作ったOSと同じOS上でのみ動く実行ファイルしか出来上がらない。
では、実行失敗を見ていきましょう。
pyinstallerはクロスコンパイラではないのでWindowsでは動かない
Windowsのエクスプローラからこのファイルをクリックしても「このファイルを開く方法を選んで下さい。」とダイアログが出る。
名前をtkinter_gui
⇒ tkinter_gui.exe
に変えればよいのかな?
# ファイル名を変更 mv ./dist/tkinter_gui ./dist/tkinter_gui.exe
変えた。再びWindowのエクスプローラからファイルをクリックで実行する。
動かない。ネット検索して調べると
pyinstallerはクロスコンパイラではない為、Windows用ならWindowsで、Linux用ならLinuxで作成する必要がある云々
結局、WindowsPCで作ったのだがWSLのUbuntuLinuxで作ったので、実行ファイルはLinuxで動くものしか出来ない。Linuxといっても別のディストリビューションのLinuxでこのファイルが動くかは試してないので不明。
WSLのUbuntuからなら動く
ならば、wsl起動中のターミナルで実行すれば動くだろう!
動いてもらわねば困る。
$ ./dist/tkinter_gui.exe
よっしゃー!動いた!
拡張子を外して元の名前に戻します。
$ mv ./dist/tkinter_gui.exe ./dist/tkinter_gui $ ./dist/tkinter_gui
ファイル名を変えただけなので、当然動く。
ターミナルで実行してみる。
# ディレクトリ構成 (ディレクトリのみ表示
!tree -d
.
├── __pycache__
├── build
│ └── tkinter_gui
└── dist
4 directories
# ディレクトリ構成 (実行ファイルの入ったdist/内のみ表示
!tree dist/
dist/
└── tkinter_gui
0 directories, 1 file
ターミナルで実行ファイルを実行。
((base) 茶屋六郎九郎:@tkinter_sample$ ./dist/tkinter_gui
※(tkinter_sampleという名前のディレクトリから実行しています)
これも動く。
おわりに
今回の場合は、他のLinuxユーザーへの配布を目的としなければ、わざわざpyファイルを実行ファイル化する意味はない。自分で使う分に関しては、そのままpyファイルを実行すればよいので。
WSLのUbuntuでtkinterが動くことと、pyinstallerがクロスコンパイラではないことが分かった、というのが今回の収穫でございました。
以上です。