Open-source project
skywind3000/PyStand avatar
skywind3000/PyStand

PyStand: a Windows launcher that runs Embedded Python without a console window

:rocket: Python Standalone Deploy Environment !!

1,207 stars146 forksC++MIT

At a glance

What is it?
PyStand is a small C++ executable that sits in front of a Python Embedded runtime, launches a .int script beside it, adds a local site-packages to the path, and can be built as a windowed or a console binary, which makes a PyQt or plain Python program a single folder you can ship.
Who is it for?
PyStand suits a Windows developer who wants to ship a Python or PyQt program as a folder with a small runtime beside it, without the size of a full installer or a bundled interpreter. It is a poor fit if you are not on Windows, since it exists to drive the Windows Embedded Python distribution, and it is a poor fit if you need a signed installer or a service, because there is no packaging around it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 80 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What PyStand actually is

PyStand is a Python standalone deploy environment, and the framing in the project description is a launcher for Python's Embedded distribution on Windows.

The background explains why it exists. Since Python 3.5, Windows has shipped with an Embedded Python, a standalone Python runtime that comes without the installer and without the usual site-packages layout. PyStand is the companion to that runtime: a launcher that finds the Embedded Python, loads your code, and gives you a program that runs like a normal Windows application.

The repository is small enough to read in one sitting. The top level has PyStand.cpp and PyStand.h, the C++ sources, CMakeLists.txt for the build, PyStand.int which is the template entry script, appicon.ico for the application icon, resource.rc for the Windows resource script, and a LICENSE. There is a .github directory and an .gitignore. The primary language is C++, and the licence is MIT, with the last push on 2026-08-03 and releases 1.1.5 from 2025-03-31, 1.1.4 from 2024-10-30 and 1.1.3 from 2024-07-29.

The topic tags list pyqt, pyqt5, pyside and pyside2, which tells you the intended audience: people shipping a desktop GUI written in a Qt binding for Python, where the usual answer is a packaging tool that bundles an entire Python distribution and every dependency into one large executable.

The four things the launcher does at startup

The functional description is short and precise, and it is worth reading as a startup sequence.

First, it is a launcher for a standalone Python environment on Windows. Second, it automatically loads the Embedded Python found in the runtime subdirectory next to PyStand.exe. Third, it automatically starts the .int program beside PyStand.exe, which is the Python code. And fourth, it automatically adds the site-packages directory beside PyStand.exe to the path, so libraries can be dropped in there.

The naming rule is what makes the folder relocatable. If you rename the executable, it loads the correspondingly named .int file, so renaming PyStand.exe to MyDemo.exe makes it load MyDemo.int.

The console behaviour is also specific. It is a windowed program with no console, but if you run it inside cmd.exe you can see the print output. So a user double-clicking the executable gets a clean GUI with no console window flashing up, while a developer running it from a terminal gets stdout and stderr, which is the behaviour that makes debugging a packaged application possible at all.

That last point connects to the recommended pattern for the entry script, which is that PyStand.int should be as small as possible, so that the traceback you get from a console run points at your own code rather than at the packaging layer.

The build, and the bitness that has to match

Building is a CMake job. You use CMake to generate PyStand.exe, or you download a prebuilt one from the Release directory.

Then the deployment steps are: download the Python Embedded version and put it in the runtime subdirectory of the directory where PyStand.exe sits. Create the Python source file PyStand.int in the same directory as PyStand.exe. Double-click PyStand.exe and it runs the code in PyStand.int.

The bitness constraint is the one that bites. If the Embedded Python is 32-bit, the PyStand CMake configuration also needs to be told -A Win32. This is the standard Windows 32-versus-64 problem, but it is easy to miss here because the mismatch shows up as a launcher that starts and then fails to find the runtime, rather than as a build error.

For debugging there is a console build. Adding -DPYSTAND_CONSOLE=ON at CMake time produces a command-line version, which is the same thing as the windowed build with the console attached, and the documentation frames it as a convenience for debugging rather than a separate mode with different behaviour.

The sizes are the other headline. Publishing a plain Python program with PyStand gives a package of about 5MB. Publishing a PyQt program with PyStand plus a slimmed-down PyQt5 gives about 14MB. Both figures are for the whole deliverable, the launcher plus the runtime plus the libraries, and they are the reason people reach for this instead of a general purpose packer: the Embedded Python runtime is already small, and the launcher adds almost nothing to it.

Installing dependencies, and the local site-packages trick

The frequently asked questions cover the two things that are not obvious.

The first is installing dependencies. The method is: make a virtual environment with a Python of the same version as your Embedded Python, pip install the modules into it, then copy the corresponding packages from site-packages into the site-packages directory next to PyStand.exe and use them from there. There is no wheel resolution step, no dependency solver, and no transitive dependency handling in the deploy process itself, which means the resolution happens in the virtual environment and the deployment is a copy.

That is a deliberate trade. You get a small package and full control over what is included, and you give up the guarantee that a tool like PyInstaller gives you, where the packaging step works out what to include. If a dependency of your dependency is missing from the copied site-packages, the failure appears at runtime on the user's machine rather than at build time on yours.

The second is seeing errors. Running PyStand.exe inside cmd.exe shows standard output and standard error. The recommended practice is to keep PyStand.int minimal, and the documentation gives the shape of that minimal entry:

python
import main
main.main()

So you write your main program into main.py, get it working in your usual way, and then import it from PyStand.int. If PyStand.int itself has a mistake, you go to a command line and run PyStand.exe to see the error. The split is deliberate: the entry file is the part that could be wrong because of the packaging, and everything else is ordinary Python that you already debugged.

There is also a small convenience API. PyStand adds an os.MessageBox(msg, title) interface, which can be used to show a simple dialog box.

Organising scripts, changing the icon, and the static entry file

Three smaller features round out the tool, and each addresses a specific annoyance.

Script organisation. You can create a script folder beside PyStand.exe and put your scripts in it. In PyStand.int you add that folder to sys.path and import from it. For distribution, compress the script folder into a script.egg file with zip, and PyStand.int detects the file, adds it to sys.path and imports from it. So a large script set ships as one file inside the package.

The icon. You can replace the appicon.ico file and recompile PyStand.exe, or use Resource Hacker to replace the icon in a downloaded Release build of PyStand.exe directly, which is the shortcut for people who do not want to run the C++ build.

The static entry file. Some users worried that a user might rename the executable but not the .int file, which would break the program. So there is an entry file named _pystand_static.int, and if the main program detects that file in its own directory it loads it in preference, and only falls back to PyStand.int if it is not there. That way the main program can be renamed freely, as long as the entry point is written in _pystand_static.int.

That last feature is a small piece of engineering that shows the author thinking about deployment rather than development. The rename-by-accident scenario is a real one for a program that gets copied around, and a fallback that resolves it is cheaper than a support question.

The documentation also points at a write-up comparing this approach with PyInstaller, and a wiki of frequently asked questions collected from other users, and the examples under the Release directory.

Editorial conclusion

PyStand suits a Windows developer who wants to ship a Python or PyQt program as a folder with a small runtime beside it, without the size of a full installer or a bundled interpreter. It is a poor fit if you are not on Windows, since it exists to drive the Windows Embedded Python distribution, and it is a poor fit if you need a signed installer or a service, because there is no packaging around it. Before adopting, build it with CMake for the same bitness as the Embedded Python you plan to ship, since a 32-bit Embedded Python needs -A Win32, and keep the entry script thin so that errors surface in a console run.

Frequently asked questions

What is PyStand and what problem does it solve?

PyStand is a small C++ Windows launcher that works with Python's Embedded distribution. It loads the Embedded Python found in the runtime subdirectory next to the executable, starts the .int script beside it, and adds a local site-packages directory to the path, so a Python or PyQt program ships as a small folder rather than a bundled executable.

How do I build PyStand and what does the deployment look like?

Use CMake to generate PyStand.exe, or take a prebuilt one from the Release directory. Then put the Python Embedded version in the runtime subdirectory next to the executable, create a PyStand.int file in the same directory, and double-click PyStand.exe. If your Embedded Python is 32-bit, configure CMake with -A Win32, and add -DPYSTAND_CONSOLE=ON to build a console version for debugging.

How do I install third-party packages with PyStand?

Create a virtual environment with a Python of the same version as your Embedded Python, pip install the modules into it, then copy the corresponding packages from site-packages into the site-packages directory next to PyStand.exe. The library adds that directory to the path automatically.

How do I debug a PyStand application?

Run PyStand.exe inside cmd.exe to see standard output and standard error, and keep the PyStand.int entry file minimal, with the pattern of importing main and calling main.main() so that errors point at your own code rather than at the packaging layer. A console build is also available by adding -DPYSTAND_CONSOLE=ON at CMake time.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. skywind3000/PyStand on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/skywind3000-pystand.svg)](https://hysenlabs.com/projects/skywind3000-pystand)

Was this useful?