Skip to content

Latest commit

 

History

History
265 lines (193 loc) · 13.1 KB

File metadata and controls

265 lines (193 loc) · 13.1 KB

About PyToExe Converter

The full story: what it is, why it exists, who needs it, how it works technically, and full specifications.

Author: Instagram @x404ctl  |  GitHub @MAliXCS


The Problem

Every Python developer eventually hits the same wall.

You build something useful — an automation tool, a data processor, a desktop app, a file organiser, a game, a utility — and you want to share it with someone. A friend. A client. A colleague. A family member.

And then you hear yourself say: "First you need to install Python. Then open a terminal. Then run pip install for these five packages. Then navigate to the folder. Then run the script with..."

Most people give up before step two.

Even sharing with other developers is painful: different Python versions, missing packages, OS differences, PATH issues. What works perfectly on your machine silently fails on theirs.

The solution is a standalone executable. A single .exe file that a user can double-click and have it just work — no Python, no terminal, no setup. Windows users expect this. They understand .exe files. They know how to double-click them.

PyInstaller has been solving this problem since 2005. It bundles a Python script and all its dependencies into a self-contained executable. It is reliable, widely used, and supports virtually every Python library.

But PyInstaller is a command-line tool. To use it properly you need to know flags, understand build modes, handle data files, manage paths, read error output, and debug silently failing builds. The barrier is high for beginners, and even experienced developers find it tedious to type and maintain.

PyToExe Converter is the missing graphical front-end for PyInstaller. It removes every barrier between your Python script and a working .exe file.


Who It Is For

User Type Their Situation What PyToExe Does for Them
Python beginners Know how to write scripts, have no idea how packaging works Point, click, done — no terminal required
Students Need to submit projects as executables Create distributable exe in under a minute
Freelancers Deliver tools to non-technical clients Client gets a double-clickable app, not a folder of .py files
Hobbyists Want to share scripts with non-developer friends/family Friends get something they understand
Developers Know PyInstaller, just want it faster Skip the CLI typing, build from GUI
Sys Admins Package Python maintenance scripts for others Portable exe tools with no Python dependency on target machines
Educators Teaching Python, want students to share their work easily One extra step that makes student projects feel real

Core Design Principles

1. Zero Barrier to Entry

You do not need to read documentation to use this app. The interface is numbered step by step: 01 Select Files, 02 Build Options, 03 Additional Files, 04 Python, then CONVERT. It is self-explanatory.

2. One File, No Framework

The entire application is py2exe_converter.py — a single Python file. No setup wizard. No installation. No dependencies beyond Python's built-in tkinter and PyInstaller. Copy the file anywhere and run it.

3. Transparency Through the Log

The Build Log shows every step PyInstaller takes, the exact command being run, the Python being used, the output path. Nothing is hidden. When something goes wrong, you can read exactly what went wrong. This respects the user's intelligence and makes debugging possible without guessing.

4. Fail Loudly and Helpfully

Most GUI wrappers around CLI tools silently succeed when things are broken — they show "Success!" and you later discover the file doesn't work. PyToExe verifies the .exe actually exists on disk after a "successful" build, detects the most common failure modes (especially antivirus deletion), and shows you specific, actionable fix instructions.

5. Dark Professional Theme

A dark, GitHub-inspired colour palette communicates seriousness. Developers spend hours looking at tools like this. The interface should not be visually tiring, and it should look like something worth using.


Technical Specifications

Runtime Requirements

Component Requirement
Python 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13+
Operating System Windows 7, 8, 8.1, 10, 11 (x86/x64)
tkinter Included with Python (no separate install)
PyInstaller 4.x or newer (auto-installed if missing)
RAM ~20 MB for the app itself; 256+ MB recommended for builds
Disk ~500 MB free for build cache; more for large apps
Network Only needed if auto-installing PyInstaller

Application Size

Metric Value
Source file ~980 lines
Disk footprint ~35 KB (single .py file)
RAM at rest ~18–25 MB
RAM during build Depends on target script; typically 100–400 MB

Architecture

py2exe_converter.py
│
├── find_python()
│   └── Locates real python.exe even when app is frozen as .exe itself
│
├── ensure_pyinstaller(python_exe)
│   └── Calls python -c "import PyInstaller" to verify, installs if missing
│
├── build_command(cfg, python_exe)
│   └── Assembles PyInstaller CLI args list + returns resolved dist path
│
├── open_folder(path)
│   └── Cross-platform folder open (os.startfile on Windows)
│
├── SplashScreen(tk.Toplevel)
│   ├── Typewriter animation via after() loop (no threading, stays on main loop)
│   ├── Blinking cursor
│   └── Dismissed by any key or click
│
└── App(tk.Tk)
    ├── find_python() called once at startup — stored as self._python_exe
    ├── _build_ui()
    │   ├── Title bar (tk.Frame — blue)
    │   ├── Scrollable canvas (tk.Canvas + inner tk.Frame)
    │   │   ├── Section 01: File rows (tk.Entry + tk.Button grid)
    │   │   ├── Section 02: Options (tk.Checkbutton)
    │   │   ├── Section 03: Extra files (tk.Listbox + tk.Scrollbar)
    │   │   ├── Section 04: Python info (tk.Label + Change button)
    │   │   ├── CONVERT button (tk.Button — full width, green)
    │   │   ├── Progress bar (ttk.Progressbar — indeterminate)
    │   │   ├── Open Folder button (hidden until success)
    │   │   └── Section 05: Build log (scrolledtext.ScrolledText)
    │   └── Status bar (tk.Frame — dark panel)
    │
    ├── _start_build()
    │   ├── Validates all inputs
    │   ├── Calls ensure_pyinstaller()
    │   ├── Disables CONVERT button
    │   └── Launches _run_build() on daemon thread
    │
    ├── _run_build(cfg)  [background thread]
    │   ├── Calls build_command() to get cmd list + dist path
    │   ├── Creates output directory
    │   ├── Launches PyInstaller via subprocess.Popen
    │   ├── Streams stdout line-by-line via self.after(0, _log_write, line)
    │   └── Always calls _build_finished() on exit (even on exception)
    │
    └── _build_finished(success, cfg)  [main thread, via after()]
        ├── Calls _unlock_ui() unconditionally (re-enables button always)
        ├── Checks os.path.isfile(exe) to verify exe actually exists
        ├── Three outcomes: real success / silent antivirus deletion / real failure
        └── Shows appropriate messagebox for each outcome

Threading Model

Building runs on a background daemon thread so the UI never freezes during a long build. All UI updates from the thread use self.after(0, callback) to post calls back to the tkinter main loop — this is the only thread-safe way to modify tkinter widgets from a non-main thread.

The _unlock_ui() method is always called when the build thread ends, even if an exception occurs. This prevents the CONVERT button from getting stuck in a disabled state.

Process Management

PyInstaller is launched via subprocess.Popen with:

Setting Value Reason
stdout=PIPE Capture output Stream to log
stderr=STDOUT Merge stderr Single stream, simpler
text=True String mode No manual decode
bufsize=1 Line-buffered Real-time log updates
CREATE_NO_WINDOW Windows flag No flash of console
No cwd= All paths are absolute; cwd caused drive-letter conflicts

The Frozen-EXE Problem (v2.1 fix)

When py2exe_converter.py is itself packaged into a .exe by PyInstaller (which is a very natural thing to do — convert the converter), sys.executable points to py2exe_converter.exe, not python.exe. If the app then tries to run sys.executable -m PyInstaller yourscript.py, it is running itself recursively, not Python.

The find_python() function detects the sys.frozen flag and falls back to:

  1. Searching shutil.which() for python, python3, py on PATH
  2. Scanning common Windows install locations using glob
  3. Each candidate is verified with a quick python --version subprocess call

This means the app works correctly whether launched as a .py file or as a compiled .exe.


What the App Generates (PyInstaller Flags)

GUI Setting PyInstaller Flag(s)
One-File mode --onefile
One-Folder mode --onedir
Console mode --console
Windowed mode --windowed
Icon selected --icon /abs/path/icon.ico
Extra file added --add-data "/abs/src;basename"
Output folder --distpath /abs/output/dir
Always applied --noconfirm (no prompts)
Always applied --name scriptname (from filename)
Work/spec dir --workpath + --specpath__pybuild_tmp__ next to script

All paths passed to PyInstaller are converted to absolute paths before the command is assembled. This avoids every class of relative-path bug.


What PyToExe Does NOT Do

Being honest about scope:

  • Does not obfuscate or encrypt code. PyInstaller-built executables can be decompiled with tools like pyinstxtractor. For commercial IP protection, additional obfuscation (e.g. Nuitka, PyArmor) is needed.
  • Does not cross-compile. Windows → Windows only. macOS and Linux produce their own native formats.
  • Does not manage virtual environments for you. Activate the right venv before building, or point Section 04 to the venv's Python manually.
  • Does not code-sign executables. Antivirus false positives require a purchased code-signing certificate to resolve permanently.
  • Does not support Python 2. End of life since January 2020.
  • Does not produce installers (MSI/NSIS). Produces an exe or folder, not a Windows installer package.

Why PyInstaller (and Not the Alternatives)?

Tool Pros Cons
PyInstaller Most widely used, best library support, excellent docs, handles 99% of packages automatically Antivirus false positives
cx_Freeze Solid, long-standing More manual configuration for complex apps
Nuitka Compiles to C, faster executables, better obfuscation 10–100x longer build times, more setup complexity
py2exe Windows-native Less maintained, limited modern Python support
Briefcase (BeeWare) Cross-platform Complex for simple scripts, requires restructuring code

PyInstaller handles the vast majority of packages automatically (numpy, pandas, PyQt, tkinter, requests, SQLAlchemy, PIL, OpenCV, and thousands more) with zero configuration. That makes it the best engine for a "just works" GUI wrapper.


Version History

Version Date Changes
v1.0 2025-01 Initial release. Basic GUI, file selection, one-file/one-folder, simple build log.
v2.0 2025-06 Full rewrite. Dark GitHub theme. Splash screen with typewriter animation. Scrollable UI. Open-folder button. Timestamped log. Colour-coded output. Improved error handling.
v2.1 2025-12 Critical bug fixes. find_python() handles frozen exe case. build_command() return value fixed. Thread always re-enables button. Removed --clean flag and cwd= override. Added exe-existence verification. Antivirus detection with actionable hints. Section 04 Python inspector with Change button.

License

MIT License. Free to use, modify, and distribute with attribution.

Copyright (c) 2025  @x404ctl  /  @MAliX

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.

Made with Python  ·  Powered by PyInstaller  ·  by @x404ctl & @MAliXCS