Launching a `.py` file on windows by creating an executable

I was trying to search up how pip install black creates a black.exe on windows, and stumbled upon easy_install.py in setuptools, and exemaker that do similar stuff, but I’m still unable to figure out how I can do what the pip install command is doing in my own project.

Essentially what I want is:

python create_exe.py foo.py --python-path path/to/python.exe

And it creates a foo.exe that will execute the Python script.

1 Like

Hi,

to convert your Python scripts to ready to use executable files, try the following link:

https://www.py2exe.org/

First of all the modern way to package your project is to use a pyproject.toml file, (preferably with a “src” layout, but flat is possible too).

https://packaging.python.org/en/latest/tutorials/packaging-projects/

If you do that, it’s simple to generate executable and .sh entry points automagickally, when your project is built for distribution using the [project.scripts] table, leaving the hard work to the build back end:

Setuptools does the job fantasticall too.

The details of how to produce a basic Windows .exe involve a bit of xml, and are inspectable in pip’s source code

1 Like

I know, but I’m trying to do this dynamically. Essentially mimicking one of these build backends myself to create a console script from a python entrypoint.

Also look at using PyInstaller Manual — PyInstaller 6.8.0 documentation as well as py2exe.

If you want to know about the gory details of how to turn python code into .exe
you could have a look at my GitHub - barry-scott/PythonWinAppPackager: Turn a python program into a windows exe package that is smaller then the others to read.

1 Like

You can adjust entries in pyproject.toml marked as dynamic with a build plugin script. It’s admittedly easier for me to say than for you to do, as I’ve already done it. But it was surprisingly straightforward.

I’m not trying to create a standalone executable. Simply a wrapper .exe that runs a Python command. Much like what a python file with a #!/usr/bin/env python shebang would do on UNIX.

You can imagine my usecase to be as follows: User supplies a python command, like python -m foo, and the program outputs a command.exe, which when ran, simply executes python -m foo.

I’m not trying to create a package.

I think I found a solution.

So setuptools ships these compiled cli.exe, cli-64.exe and so on binaries. The way they work is by renaming the binary, and by providing a script alongside it, such as:

  • Rename cli.exe to myapp.exe
  • Create a myapp-script.py file, with a shebang:
    #!/path/to/python
    print("Hello world")
    

Now if you run myapp.exe (or just myapp if it is in PATH), you’ll get Hello world.


This is the source code for building cli.exe: launcher.c

2 Likes

Well done for solving it already, but all the above could be done in code that runs in a build environment, that builds a skeleton setup around the user’s foo script or command.

As I said, this is not being done as a build step. This is what I want to happen at runtime, as it’s the user that will provide the .py file (for example).

Thanks for the help though, ended up digging through the test suites of pip to stumble upon this.

You’re welcome. Maybe my suggestion wasn’t compatible with what you had in mind, but I’ve never got the impression any of the “all in one” exe bundlers work fantastically well (where as pipx say, does :slight_smile: ), so that’s just how I’d prefer to approach it.

2 Likes

To be fair, the exe bundlers are generally doing almost the same thing that the Pip/Setuptools toolchain does - they just also provide a Python interpreter in their bundle (and some of them have a self-extracting zip alternative). Pipx is again similar, but the other way around: starting with a full (sort of) Python (virtual) environment, and then adding the project into that.

1 Like

I think you’re looking for something like PyApp.

1 Like

Not quite, I’m not looking for a standalone binary, just a wrapper that executes a shell/python script.


Also, I found another neat solution: simply rename your foo.bat script file to foo.cmd, put it in PATH, and suddenly foo is an executable command now.

This is how npm seems to install console scripts. I wonder if python could start doing the same.

@tusharsadhwani, it seems like you have found what you need.

Maybe you could find some more inspiration in those:

1 Like

As far as I can tell, pip vendors a copy of distlib to handle this:

1 Like

Thanks! simple_launcher is actually pretty neat.

I kinda built a standalone thing out of the setuptools’ launcher.c myself as well: executable · PyPI

But simple_launcher looks more flexible.

@tusharsadhwani

Aside: The documentaton for your executable project mentions python setup.py sdist bdist_wheel, but this is deprecated and should not be used, see page linked below:

https://packaging.python.org/en/latest/discussions/setup-py-deprecated/

Yeah, that is part of my cookiecutter template, I’ll migrate away from it someday.

1 Like