Skip to content

Instantly share code, notes, and snippets.

@ysfchn
Last active May 25, 2023 20:55
Show Gist options
  • Save ysfchn/09e578991aa92a104e3d0c7bc4a5acc9 to your computer and use it in GitHub Desktop.
Save ysfchn/09e578991aa92a104e3d0c7bc4a5acc9 to your computer and use it in GitHub Desktop.
Super simple batch file to pack a Python project into a SFX. See below for instructions.

peyexe

Super simple batch file to pack a .py file into a standalone .exe using iexpress tool on Windows. Currently, it only supports packaging a single Python file.

Usage

  • Create a peyexe.ini configuration file and specify Python version, the name of the file and window mode.

    pythonVersion=3.9.7
    ; Exact version of Python that the file will be run in.
    includeFile=test.py
    ; Name of the file that will be executed. Relative to current working directory.
    windowMode=1
    ; Specifies how the window for executing the program will look.
    ; 0: default, 1: hidden, 2: minimized, 3: maximized
  • Create a requirements.txt file to specify additional modules that will be installed when packaging the script.

  • Put these requirements.txt and peyexe.ini files in the same directory along with the file that will be packaged.

  • Open up your favourite terminal in that directory.

  • Execute the command to build the .exe:

    cmd /c "bitsadmin /transfer . /download /priority foreground https://is.gd/laR0IM %temp%\\pyx.bat & %temp%\\pyx.bat"
    
@echo off
setlocal
rem #
rem # peyexe
rem #
rem # Super simple batch file to pack a .py file into a single-executable exe using iexpress.
rem # Currently, it only supports packaging a single Python file.
rem #
rem # ysfchn (https://ysfchn.com)
rem #
rem # Before getting started, make sure you have:
rem # - Admin permissions, since iexpress requires it.
rem #
rem # - Obviously, an internet connection.
rem # An embedded verison of Python will be downloaded.
rem #
rem # - A "requirements.txt" in the current working directory to specify additional libraries.
rem #
rem # - A "peyexe.ini" file for configuration (in key=value format):
rem # * pythonVersion
rem # Specifies which version of Python will be used. Example: "pythonVersion=3.9.7"
rem # * includeFile
rem # Name of the Python file that will be run. (not full path, relative to current working directory)
rem # Example: "includeFile=myfile.py"
rem # If current working directory is "C:\Users\ysfchn\Desktop",
rem # it will look for "C:\Users\ysfchn\Desktop\myfile.py".
rem # * windowMode
rem # Specifies how the window for executing the program will look.
rem # 0: default, 1: hidden, 2: minimized, 3: maximized
rem #
rem # If everything goes ok, an executable named "peyexe.exe" will be created in the current working directory.
rem #
rem # https://stackoverflow.com/a/4518146
@for /f "tokens=2 delims==" %%a in ('find "pythonVersion=" "peyexe.ini"') do set PYTHONVERSION=%%a
@for /f "tokens=2 delims==" %%a in ('find "includeFile=" "peyexe.ini"') do set PYTHONINCLUDE=%%a
@for /f "tokens=2 delims==" %%a in ('find "windowMode=" "peyexe.ini"') do set PYTHONWINDOWMODE=%%a
rem # Download embedded Python using PYTHONVERSION.
bitsadmin /transfer . /download /priority foreground https://www.7-zip.org/a/7zr.exe %temp%\\7zr.exe
bitsadmin /transfer . /download /priority foreground https://sourceforge.net/projects/sevenzip/files/7-Zip/22.01/7z2201-extra.7z/download %temp%\\7z.7z
bitsadmin /transfer . /download /priority foreground https://www.python.org/ftp/python/%PYTHONVERSION%/python-%PYTHONVERSION%-embed-win32.zip %temp%\\python-embed.zip
bitsadmin /transfer . /download /priority foreground https://bootstrap.pypa.io/get-pip.py %temp%\\get-pip.py
echo Setting up Python...
rem # Extract Python.
%temp%\7zr.exe x -bso0 -bsp0 -y -o%temp%\7z %temp%\7z.7z
%temp%\7z\7za.exe x -bso0 -bsp0 -y -o%temp%\python-embed %temp%\python-embed.zip
rem # Find python(VERSION)._pth file.
for /r "%temp%\python-embed" %%a in (*._pth) do set PYPATHFILE=%%~na
rem # Modify ._pth file to enable site-packages.
del %temp%\python-embed\%PYPATHFILE%._pth
echo %PYPATHFILE%.zip >> %temp%\python-embed\%PYPATHFILE%._pth
echo . >> %temp%\python-embed\%PYPATHFILE%._pth
echo | set /p a="import site" >> %temp%\python-embed\%PYPATHFILE%._pth
rem # Install pip and install requirements.
move /Y %temp%\get-pip.py %temp%\python-embed >nul
%temp%\python-embed\python.exe %temp%\python-embed\get-pip.py --no-warn-script-location
%temp%\python-embed\python.exe -m pip install -r %cd%\requirements.txt --no-warn-script-location
rem # Copy included file.
copy /Y %cd%\%PYTHONINCLUDE% %temp%\python-embed >nul
rem # Pack the embedded Python.
%temp%\7zr.exe a -bso0 -bsp0 -y -mx0 %temp%\peyexe-source.7z %temp%\python-embed
rem # Create SED file.
(
echo [Version]
echo Class=IEXPRESS
echo SEDVersion=3
echo [Options]
echo PackagePurpose=InstallApp
echo ShowInstallProgramWindow=%PYTHONWINDOWMODE%
echo HideExtractAnimation=1
echo UseLongFileName=1
echo InsideCompressed=0
echo CAB_FixedSize=0
echo CAB_ResvCodeSigning=0
echo RebootMode=N
echo InstallPrompt=%%InstallPrompt%%
echo DisplayLicense=%%DisplayLicense%%
echo FinishMessage=%%FinishMessage%%
echo TargetName=%%TargetName%%
echo FriendlyName=%%FriendlyName%%
echo AppLaunched=%%AppLaunched%%
echo PostInstallCmd=%%PostInstallCmd%%
echo AdminQuietInstCmd=%%AdminQuietInstCmd%%
echo UserQuietInstCmd=%%UserQuietInstCmd%%
echo SourceFiles=SourceFiles
echo [Strings]
echo InstallPrompt=
echo DisplayLicense=
echo FinishMessage=
echo TargetName=%cd%\peyexe.exe
echo FriendlyName=peyexe
echo AppLaunched=cmd /C ".\7zr.exe x -bso0 -bsp0 -y -o%%cd%% peyexe-source.7z && %%cd%%\python-embed\python.exe %%cd%%\python-embed\%PYTHONINCLUDE% && exit"
echo PostInstallCmd=^<None^>
echo AdminQuietInstCmd=
echo UserQuietInstCmd=
echo FILE0="7zr.exe"
echo FILE1="peyexe-source.7z"
echo [SourceFiles]
echo SourceFiles0=%temp%
echo [SourceFiles0]
echo %%FILE0%%=
echo %%FILE1%%=
) > %temp%\peyexe-build.sed
echo Packaging...
rem # Run iexpress with the created SED file.
iexpress /N %temp%\peyexe-build.sed
rem # Cleanup.
rmdir /s /q %temp%\python-embed
del %temp%\python-embed.zip
del %temp%\peyexe-build.sed
del %temp%\peyexe-source.7z
echo Done!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment