Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

pybin

Simple wrapper around PyInstaller to build a single-file executable from a Python script, with optional cleanup of build artifacts.

Requirements

  • Python 3.9+
  • PyInstaller available on PATH (e.g., pip install pyinstaller)

Usage

# 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

What it does

  1. Expands any glob patterns in the inputs, de-duplicates, and filters out underscore-prefixed files (when building >1 file) and anything matching --exclude patterns.
  2. Validates each input file exists and ends with .py.
  3. Runs pyinstaller --onefile <script> for each file, with paths anchored to the script's directory (not the CWD).
  4. Optionally removes build/ and the generated .spec unless you keep them via flags.
  5. Leaves the resulting executable in the dist/ folder next to the script by default.
  6. When building multiple files, prints a summary at the end; exits non-zero if any file failed.

Flags

FlagDescription
--exclude / -x <PATTERN>Skip files whose name or full path matches this fnmatch pattern (e.g. _*, *test*). Repeat to add more patterns.
--include-underscoreWhen building multiple files, include underscore-prefixed files (e.g. _core.py) instead of auto-skipping them.
--keep-spec / --no-keep-specKeep or delete the generated .spec file after the build (default: keep).
--keep-buildKeep 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.

Notes

  • The tool does not install PyInstaller for you; ensure it is installed and on PATH.
  • The .spec file is regenerated each run unless you keep and reuse it with --keep-spec.
  • By default the dist/, build/, and .spec live in the same directory as the input script (even if you run pybin from elsewhere).
  • The final executable path defaults to <script_dir>/dist/<script-name>.exe on Windows.

Shell Completion

To enable tab completion in PowerShell:

  1. Create the completions directory:

    mkdir ~\Documents\PowerShell\completions
  2. Generate the completion script:

    pybin --show-completion > ~\Documents\PowerShell\completions\pybin-completion.ps1
  3. Add to your PowerShell profile ($PROFILE):

    # Load all completion scripts
    Get-ChildItem "$HOME\Documents\PowerShell\completions\*.ps1" | ForEach-Object { . $_ }
  4. 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.