SyntaxHighlighter

2018年6月26日火曜日

Single Binary StacklessPython 3.6.4 L8 リリース

Single Binary StacklessPython 3.6.4 L8 リリース

業務の効率化や Python インタプリタの勉強も兼ねて、 StacklessPython を 1 バイナリ化していましたが、バージョン L8 まできました。

GitHub のリリースページからダウンロードできます。

今回は、主に以下の変更をしました。

  • tkinter のサポート
  • EXE 化の実験的サポート
  • Windows Subsystem 版のサポート

tkinter のサポート

これまでに Python の標準ライブラリは、ほぼすべてサポートしていましたが、 tkinter はいくつかの理由でサポートしていませんでした。

tkinter をサポートし、1 バイナリで実行するには、 tcl/tk のライブラリを静的にリンクする必要があります。
また、 tcl/tk は、いくつかの *.tcl ファイルを必要とするので、こちらについても対応する必要があります。

静的リンクについては、 nmake -f makefile.vc core OPTS=static のように OPTS として static を指定すれば、静的リンク版をビルドできるので、こちらを使うことになります。

一方で、*.tcl ファイルの抱き込みについては、やや面倒です。

*.tcl ファイルの抱き込み

tcl では、Tcl_Filesystem という構造体で、複数のファイルシステムを持つことができます。
これは一言で言うと Python の path_hooks に相当するものです。
今回は embeddedFilesystem というファイルシステムを作成し、 embeddedfs:/tcl8.6/init.tcl のように embeddedfs:/ で始まる仮想的なパスが指定された場合に、バイナリの中に保持しているファイルの中身を返すようにしています。

詳しくは tclEmbeddedFilesystem.c を参照してください。

EXE 化の実験的サポート

せっかくなので、おまけの機能として EXE 化の機能を付けてみました。
なお、元々、標準ライブラリ外の機能は考慮していないので、py2exe や PyInstaller の代わりには使えません。あくまで、標準ライブラリだけを使って書けるスクリプトの EXE 化ができます。

例えば下記のように、 tk でウィンドウを作成し、クリックでカウントアップするだけのプログラムを EXE 化してみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# coding: utf-8
 
# counter.py
 
import tkinter as tk
import tkinter.ttk as ttk
 
 
class Counter(ttk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        var = tk.StringVar()
        var.set("0")
        label = ttk.Label(self, textvariable=var, anchor=tk.CENTER, font=("", 30))
        label.pack(expand=True, fill=tk.BOTH)
        label.bind("<Button-1>", self.increment)
        label.bind("<Button-3>", self.decrement)
        self.var = var
        self.count = 0
 
    def increment(self, event):
        self.count += 1
        self.var.set("%d" % self.count)
 
    def decrement(self, event):
        self.count -= 1
        self.var.set("%d" % self.count)
 
 
root = tk.Tk()
a = Counter(root)
a.pack(expand=True, fill=tk.BOTH)
root.mainloop()

今回の Single Binary StacklessPython では、上記のように tkinter を使うような場合も、実行することができます。

これを、単一の EXE にするには、下記のようにします。
ただし、これはまだ実験的な機能なので、将来は仕様を変更するかもしれません。

1
python.exe -m exepy sample.exe counter.py

上記を実行すると sample.exe が生成されます。

サイズは 14MB ぐらいになりますが、テンポラリディレクトリにファイルを展開したりはしないので、かなり高速に実行されます。

Windows Subsystem 版のサポート

今回から pythonw.exe のように、コンソール画面が表示されないバイナリを作っておきました。

こちらは、主に GUI を使うスクリプトを EXE 化する際に使うと便利です。

Python, tcl/tk の実装の勉強にもなり、 AppVeyor の利用の勉強にもなりましたが、すべての標準ライブラリを 1 バイナリに収めたので、そろそろ終了にする予定です。

0 件のコメント:

コメントを投稿