【5分解決】Pythonアプリの実行ファイル化|Nuitkaならコマンド1行で完了!

こんな経験ありませんか🤔?

  • 「作ったPythonアプリを友達に使ってもらいたいけど...」
  • 「でも相手のPCにはPythonが入ってない」
  • 「『Pythonをインストールして、ライブラリも入れて...』って説明するのが面倒」

こういった悩みはファイルを実行ファイル化すれば、これらの問題が一瞬で解決します🤩 といっても、WindowsのWSLの実行ファイル化の実験なので、Windowsの純粋な実行ファイル化については近いうちにまとめようと思います。

実行ファイル化のメリット

  • ファイル1つ渡すだけでOK … 配布が簡単
  • 相手のPCにPythonがなくても動く … Python不要
  • ライブラリのバージョン違いでエラーが起きない … 環境依存関係の悩み解消

今回はPythonアプリを実行ファイルにするNuitkaの使い方について書いています。 『たった5分でHello Worldが実行ファイルに!』というのは大げさかもしれませんが、開発環境のインストールから実行ファイル化までの手順をなぞってみます。

今回は以下のことができるようになることを目指しています。

  • NuitkaPythonファイルを実行ファイルに変換にする
  • 他の人にPythonアプリを簡単に配布可能にする

たった5分で完成!Hello Worldを実行ファイル化

まずは、簡単なHello Worldを出力をするPythonのプログラムを実行ファイル化するという作業を行ってみます。

まずは事前にインストールするバイナリのパッケージをインストールしておきます。

$ sudo apt update
$ sudo apt install patchelf

続いて、仮想環境については従来パターンとuvを使用するパターンがありますので、どちらかを選んで作業を行ってください。

  • venvpipを使用するパターン
  • uvを使用するパターン

仮想環境をvenvとpipで使用するパターン

# 作業用ディレクトリの作成
$ mkdir ~/nuitka && cd ~/nuitka
# Pythonの仮想環境を作成し有効化する
$ python -m venv venv
$ source ./venv/bin/activate
# インストール
$ pip install nuitka

仮想環境をuvで使用するパターン

【参考】 uepon.hatenadiary.com

# 作業用ディレクトリの作成
$ mkdir ~/nuitka && cd ~/nuitka
# Pythonの仮想環境を作成し有効化する
$ uv venv
$ source ./venv/bin/activate
# インストール
$ uv pip install nuitka

PythonHello Worldプログラムを準備する

まずは、PythonHello Worldという文字列を出力するプログラムを作成します。

hello.py

print("Hello, World!")
print("Pythonアプリをexe化します!")
input("Enterで終了...")

これでプログラムの作成ができました。

実行ファイル化する

nuitkaの実行(実行ファイル化)を行います。以下の作業をするとhello.pyがhello.binと変換(実際はコンパイル)されます。

# 実行ファイル化
$ nuitka --onefile hello.py

# 実行ファイルの実行
./hello.bin

結果

  • hello.binファイルが生成される
  • Python環境がないPCにコピーしても実行できる
  • WSLで実行した場合はWSL上の実行ファイルとなる(異なるディストリビューション名でも動作すると思う、ただし、Windowsダブルクリックしても動作しません、WindowsPython環境であれば実行可能になると思いますが要調査)
  • ファイルサイズは実行ファイル化するとかなり大きくなるが、それでも同様の変換をするPyInstallerの1/3〜1/2程度になる

Nuitkaとは

では、改めてNuitkaについて説明をします。

基本概念

  • 動作原理 … PythonコードをC言語に変換 → コンパイルして実行ファイル化
  • 対応バージョン … Python 2.6~2.7、3.4~3.13
  • ライセンス … Apache 2.0(商用利用可能)

主な特徴

  • C言語変換により通常のPython実行より高速
  • 効率的な変換により軽量
  • Zstandardによる圧縮でさらにサイズ削減
  • ほぼ全てのPythonライブラリに対応

⚠️ 変換はコンパイル&ビルドなので時間が必要(実行時の高速化との引き換え)

実行時のコマンドラインオプション

基本オプション

オプション 機能 使用場面 具体例
--onefile 全てを一つのexeファイルに圧縮 単一ファイルでの配布(最推奨) nuitka --onefile app.py
--follow-imports インポートファイルを自動収集 外部ライブラリ使用時(必須級) 上記に追加
--standalone 実行に必要なファイルをフォルダに格納 フォルダごと配布したい場合 nuitka --standalone app.py
--disable-console 実行時のターミナル非表示 GUIアプリケーション用 GUI用途で追加

高度なオプションの使用例

以下のようにすることで生成結果を変えることができます。今回の例ではWindowsMacのバイナリを変換することはできないので注意です。

# Windowsの実行ファイルを作る具体例
$ nuitka --onefile --follow-imports --disable-console --windows-icon-from-ico=icon.ico \
           --product-name="My App" --file-description="Python製アプリ"  --product-version="1.0.0" app.py

# Linux/Macの実行ファイルを作る具体例
$ nuitka --onefile --follow-imports --enable-plugin=tk-inter app.py

実践例 レベル1 シンプルなCLIアプリ

コマンドラインアプリであれば以下のように簡単に変換ができます。

# calc.py - 簡単な電卓
def main():
    print("=== Python製電卓 ===")
    while True:
        try:
            expr = input("計算式を入力 (qで終了): ")
            if expr.lower() == 'q':
                break
            result = eval(expr)  # 注:実際のアプリでは使用禁止
            print(f"結果: {result}")
        except Exception as e:
            print(f"エラー: {e}")

if __name__ == "__main__":
    main()

実行例

$ nuitka --onefile --follow-imports calc.py
$ ./calc.bin

実践例 レベル2 GUIアプリ(tkinterフレームワーク使用)

GUIアプリでtkinterフレームワークを使用する場合には事前にtkinterモジュールを導入する必要があります。

# gui_app.py - シンプルなGUIアプリ
import tkinter as tk
from tkinter import messagebox

def show_message():
    messagebox.showinfo("メッセージ", "Nuitkaでビルドされました!")

root = tk.Tk()
root.title("Nuitka GUI Test")
root.geometry("300x200")

button = tk.Button(root, text="クリック", command=show_message)
button.pack(pady=50)

root.mainloop()

実行例

# tkinterのインストール
$ sudo apt update
$ sudo apt install python3-tk
# 実行ファイル化
$ nuitka --onefile --follow-imports --disable-console --enable-plugin=tk-inter gui_app.py

実践例 レベル3 外部ライブラリ使用

外部ライブラリとしてHTTPライブラリの定番であるrequestsを使用した例です。

参考 【Python】気象庁API から天気予報を取得してみた #気象データ - Qiita

# web_app.py - requests使用例
"""
web_app.py
気象庁 JSON から “今日〜明後日” の天気と直近 POP(降水確率) を取得

参考:
  https://www.jma.go.jp/bosai/forecast/data/forecast/<area>.json
  ※ area は都道府県コード。東京は 130000
"""
import requests
from datetime import datetime, timezone, timedelta

AREA_CODE = "130000"               # ← 他県にしたい場合はコードを変える
URL = f"https://www.jma.go.jp/bosai/forecast/data/forecast/{AREA_CODE}.json"

def fetch_forecast(area_code: str = AREA_CODE) -> list[tuple[str, str, str]]:
    """気象庁 JSON から (時刻, 天気, 降水確率) のタプルを返す"""
    res = requests.get(
        f"https://www.jma.go.jp/bosai/forecast/data/forecast/{area_code}.json",
        timeout=5,
    )
    res.raise_for_status()
    data = res.json()

    # 日ごとの天気(3日分): timeSeries[0]
    ts_weather = data[0]["timeSeries"][0]
    times = ts_weather["timeDefines"]          # ISO8601 +09:00
    weathers = ts_weather["areas"][0]["weathers"]

    # 直近 6h ごとの降水確率: timeSeries[1]
    # 0,6,12,18 時の計 5 コマ分が入っている(⾏政区により数は変わる)
    pops = data[0]["timeSeries"][1]["areas"][0]["pops"]

    # 「今日・明日・明後日」用に先頭 3 要素だけ使う
    return list(zip(times[:3], weathers[:3], pops[:3]))

def main() -> None:
    try:
        for time_iso, weather, pop in fetch_forecast():
            # ISO8601 → datetime へ (JST)
            dt = datetime.fromisoformat(time_iso).astimezone(
                timezone(timedelta(hours=9))
            )
            print(f"{dt:%Y-%m-%d %H:%M} : {weather.replace(' ','')} / 降水確率 {pop}%")
    except requests.exceptions.RequestException as e:
        print(f"通信エラー: {e}")
    except KeyError as e:
        print(f"JSON 解析エラー: {e}")

if __name__ == "__main__":
    main()
$ nuitka --onefile --follow-imports --include-package=requests --include-package=urllib3 web_app.py

公式リソース

おわりに

実際にNuitkaを触ってみると、「こんなに簡単に実行ファイルが作れるんだ!」という驚きがありました😲。特に、「Pythonアプリを人に渡すのって面倒だなあ...」と思っていた問題が、たった一行のコマンドで解決されるのは感動的ですらあります。Windowsのネイティブな実行ファイル化についてはまだ出来ていないので試してみようと思います。