Simple wrapper around PyInstaller to build a single-file executable from a Python script, with optional cleanup of build artifacts.
- Python 3.9+
- PyInstaller available on PATH (e.g.,
pip install pyinstaller)
# Basic build (keeps .spec, cleans build/ afterward)
pybin my_script.py
# Build multiple files at once
pybin a.py b.py c.py
# Build via a glob. If your shell already expands the glob (e.g. PowerShell for
# relative paths), pybin just receives the expanded list. Otherwise quote it so
# pybin expands it itself:
pybin "src/*.py"
pybin "src/**/*.py"
# Skip helper/private modules. Underscore-prefixed files (e.g. _core.py) are
# auto-skipped when building >1 file; override with --include-underscore.
pybin src/*.py --include-underscore
# Exclude by fnmatch pattern (repeatable). Matches name or full path.
pybin src/*.py -x "*test*" -x "experimental_*.py"
# Build to a custom output directory
pybin my_script.py --output-dir D:/Apps/dist
# Same default dist/ folder, but a different executable name (single-file only)
pybin my_script.py --name my_script_next
# or: pybin my_script.py -n my_script_next
# Remove the .spec file after build
pybin my_script.py --no-keep-spec
# Keep the build directory (for debugging or inspection)
pybin my_script.py --keep-build
# Keep both .spec and build/
pybin my_script.py --keep-spec --keep-build- Expands any glob patterns in the inputs, de-duplicates, and filters out
underscore-prefixed files (when building >1 file) and anything matching
--excludepatterns. - Validates each input file exists and ends with
.py. - Runs
pyinstaller --onefile <script>for each file, with paths anchored to the script's directory (not the CWD). - Optionally removes
build/and the generated.specunless you keep them via flags. - Leaves the resulting executable in the
dist/folder next to the script by default. - When building multiple files, prints a summary at the end; exits non-zero if any file failed.
| Flag | Description |
|---|---|
| --exclude / -x <PATTERN> | Skip files whose name or full path matches this fnmatch pattern (e.g. _*, *test*). Repeat to add more patterns. |
| --include-underscore | When building multiple files, include underscore-prefixed files (e.g. _core.py) instead of auto-skipping them. |
| --keep-spec / --no-keep-spec | Keep or delete the generated .spec file after the build (default: keep). |
| --keep-build | Keep the build directory after the build (default: removed). |
| --output-dir <PATH> | Optional output directory for the final executable (default: <script_dir>/dist). |
| --name / -n <NAME> | Base name of the built executable (no .exe); default: script stem. Output path is still <dist>/<NAME>.exe. Passed to PyInstaller as --name. Only valid when building a single file. If you use a custom .spec with a fixed EXE(name=...), you may need to match that or rely on PyInstaller overriding it. |
- The tool does not install PyInstaller for you; ensure it is installed and on PATH.
- The
.specfile is regenerated each run unless you keep and reuse it with--keep-spec. - By default the
dist/,build/, and.speclive in the same directory as the input script (even if you runpybinfrom elsewhere). - The final executable path defaults to
<script_dir>/dist/<script-name>.exeon Windows.
To enable tab completion in PowerShell:
-
Create the completions directory:
mkdir ~\Documents\PowerShell\completions
-
Generate the completion script:
pybin --show-completion > ~\Documents\PowerShell\completions\pybin-completion.ps1
-
Add to your PowerShell profile (
$PROFILE):# Load all completion scripts Get-ChildItem "$HOME\Documents\PowerShell\completions\*.ps1" | ForEach-Object { . $_ }
-
Reload your profile:
. $PROFILE
Note: Avoid using --install-completion as it appends directly to your profile without formatting and can create duplicates. Use --show-completion and manually manage completion scripts instead.