Pythonで便利なツールを作っても、相手の環境にPythonが入っていないと実行してもらえません。
特に配布を考えると「Pythonを入れてください」と説明するだけでハードルが上がってしまいます。
私自身も過去に「Pythonがないから動かせない」と言われたことがあり、配布の難しさを感じました。

この記事では、ChatGPTで作ったパスワード生成プログラムを例に、PyInstallerを使ってPythonがない環境でも動く実行ファイルを作る方法を紹介します。
配布形式としてonefileとonedirを比較し、注意点やおすすめの方法も整理します。

この記事で分かること

  • Python未導入環境でも動かせる実行ファイルの作り方
  • PyInstallerの基本と注意点
  • onefileとonedirの違い
  • ChatGPTを活用したコード生成の例
  • 実用的なパスワード生成ツールをEXE化する手順

PyInstallerとは?

PyInstallerは、Pythonで作ったプログラムを実行ファイル(WindowsならEXE)に変換するツールです。
利用者の環境にPythonがなくても動かせるのが最大の利点です。

ただし、注意点もあります。
作成した実行ファイルは逆コンパイルやデバッグツールで解析されやすいため、商用アプリを完全に守ることはできません。
配布は可能ですが、あくまで「便利に使える」程度に考え、セキュリティが重要な部分は別の方法で対策が必要です。

私の考えでは、PyInstallerは「小規模なツールを人に配布したい」「自分の環境以外で簡単に動かしたい」といった目的に適しています。
配布の敷居を下げる手段として非常に有効です。

サンプルアプリ:パスワード生成CLI

ここからは、サンプルとしてパスワード生成ツールを取り上げます。
仕様は次の通りです。

  • 数字、小文字、大文字、記号を指定可能
  • 文字数、生成数を指定可能
  • コマンドラインで実行可能

ChatGPTへの指示文例

私はこのプログラムをChatGPTに依頼して作りました。
実際に使った指示文は次の通りです。

Pythonで実行可能なパスワード生成ツールを作りたいです。
条件は以下です:
・数字、小文字、大文字、記号を指定可能
・文字数、生成数を指定可能
・コマンドラインから実行可能にしてください
・argparseを使ってください

このように要件を整理して伝えると、実用的なコードが提案されます。
私はそのコードを確認し、必要に応じて微調整しました。

実装コード(全文)

以下に全文を折りたたみ式で掲載します。

パスワード生成ツールのコード
# password_gen.py
import argparse
import string
import secrets
import sys

DEFAULT_SYMBOLS = "!@#$%^&*()-_=+[]{};:,.?/\\"

def build_pool(kinds, symbols):
    pools = {}
    if "digits" in kinds:
        pools["digits"] = string.digits
    if "lower" in kinds:
        pools["lower"]  = string.ascii_lowercase
    if "upper" in kinds:
        pools["upper"]  = string.ascii_uppercase
    if "symbols" in kinds:
        pools["symbols"] = "".join(dict.fromkeys(symbols))
    if not pools:
        raise ValueError("少なくとも1種類を指定してください")
    return pools

def generate_one(length, pools):
    password_chars = [secrets.choice(chars) for chars in pools.values()]
    all_chars = "".join(pools.values())

    if length < len(password_chars):
        raise ValueError("長さが短すぎます")

    for _ in range(length - len(password_chars)):
        password_chars.append(secrets.choice(all_chars))

    for i in range(len(password_chars) - 1, 0, -1):
        j = secrets.randbelow(i + 1)
        password_chars[i], password_chars[j] = password_chars[j], password_chars[i]

    return "".join(password_chars)

def main():
    parser = argparse.ArgumentParser(description="パスワード生成ツール")
    parser.add_argument("-l", "--length", type=int, default=16, help="パスワード長")
    parser.add_argument("-k", "--kinds", nargs="+", choices=["digits", "lower", "upper", "symbols"],
                        default=["digits", "lower", "upper", "symbols"], help="使用する文字種")
    parser.add_argument("-n", "--count", type=int, default=1, help="生成数")
    parser.add_argument("--symbols", type=str, default=DEFAULT_SYMBOLS, help="記号セット")

    args = parser.parse_args()

    try:
        pools = build_pool(args.kinds, args.symbols)
        for _ in range(args.count):
            print(generate_one(args.length, pools))
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)

if __name__ == "__main__":
    main()

実行例

作成したコードは以下のように実行できます。
以下は、パスワードの長さが20文字、パスワードの種類が半角数字、半角英字の大文字・小文字、記号、3つのパスワードを生成します。

python password_gen.py -l 20 -k digits lower upper symbols -n 3

実行結果の例は下記です。
パスワードはランダムで生成するため、実行結果は毎回変わります。

Gb}b@Edp0m?&_oSJD($W
#8z^=mw,f6OKi1jYMMOH
T3p:74ep0?3&^V!yLjoc

私の考えでは、このような小さなツールはChatGPTで生成して調整するのが効率的です。

PyInstallerで実行ファイルを作る

パスワード生成ツールをEXE化するには、PyInstallerを使います。
基本の使い方はシンプルで、コマンド一つで実行ファイルを生成できます。

PyInstallerを使用する場合、下記のコマンドを実行してPyInstallerライブラリをインストールします。

pip install pyinstaller

ライブラリを入れる環境を分けたい場合、以下の記事を参考にvenvを使用してください。

onedir(フォルダ配布)

最初に紹介するのはonedir形式です。
これは「1つのフォルダにEXE本体と必要なDLLをまとめる」方式です。

pyinstaller --name passgen password_gen.py

このコマンドを実行すると、dist\passgen\ フォルダが作られ、その中に passgen.exe が生成されます。
配布時はフォルダごとZIPにまとめれば十分です。

パスワード生成ツールを実行する場合、dist\passgen\ フォルダに移動して次のように実行します。
コマンドの最初にpythonを付けなくても実行することができます。

passgen.exe -l 20 -k digits lower upper symbols -n 3 

メリットは起動が速く、誤検知も少なめな点です。
ファイル数は多くなりますが、安定して動かせる配布方法です。

私の経験上、初めて配布するならonedirが安心です。
配布相手にも「ZIPを解凍してEXEを起動してください」と伝えれば問題なく使ってもらえます。

onefile(単一ファイル配布)

次にonefile形式です。
単一のEXEファイルとして配布できるため、見た目はすっきりしています。

pyinstaller --name passgen -F password_gen.py

この場合、dist\passgen.exe という1つのファイルだけが生成されます。
配布は非常に簡単で、1ファイルを送るだけで済みます。
onefileの場合もonedirと同じように実行できます。

しかし、onefileにはデメリットがあります。
起動時に内部で自己展開を行うため、数秒の遅延が発生します。
また、セキュリティソフトに誤検知されやすく、起動できないケースもあります。

私の考えでは、配布の見た目は魅力的ですが、トラブル回避のためにはonedirを選ぶのが現実的です。

onefileを使うときの注意点

どうしてもonefileで配布したい場合、次の注意点を理解しておく必要があります。

  1. 起動遅延
    実行のたびに自己展開が行われるため、数秒かかることがあります。
  2. 一時フォルダに展開
    Windowsのユーザープロファイル配下に一時フォルダを作り、そこに展開します。
    セキュリティソフトや権限設定によっては失敗する場合があります。
  3. ウイルス誤検知
    onefileの挙動はマルウェアに似ているため、セキュリティソフトにブロックされやすいです。
    --noupx オプションを付けて圧縮を無効にすると改善する場合があります。
  4. 外部ファイル同梱の工夫
    データを同梱する場合、sys._MEIPASS を利用する必要があり、開発が複雑になります。

これらの点を考慮すると、簡単なツールはonedirで配布し、どうしても単一ファイルにしたいときだけonefileを選ぶのが賢明です。

配布の際の補足

配布するときは次のような工夫をすると利用者に安心してもらえます。

  • ZIP形式でまとめる
    フォルダ配布なら必須です。
  • VirusTotalでチェック
    配布前にウイルス判定されないか確認しておくと信頼度が上がります。
  • ハッシュ値を添付
    ZIPのSHA256を提示しておけば、改ざんされていないことを証明できます。

私も配布前にVirusTotalで確認し、ZIPファイルのハッシュを添えるようにしています。
特に知らない相手に渡すときは安心感が大きく変わります。

まとめ

Pythonがなくても動く実行ファイルを作れると、配布のハードルが大きく下がります。
PyInstallerを使えば、ChatGPTで作った小さなツールをそのままEXEに変換でき、誰でも簡単に利用できます。
onefileとonedirには一長一短がありますが、私としては安定性の高いonedirをおすすめします。

ChatGPTを活用してコードを書き、PyInstallerで配布可能な形にする流れは、個人開発にとって強力な武器になります。
「Pythonを入れてください」と説明しなくても済むため、多くの人に使ってもらいやすくなります。

今後、今回のCLIツールをさらに拡張して、GUI化したアプリの配布方法について紹介する予定です。
配布体験をより身近にする手順を解説しますので、楽しみにしていてください。