Announcement: PyApp

Now that Hatch has been released with this, it’s time to finally show: PyApp

PyApp is a runtime installer for Python applications. At build-time you configure environment variables that control runtime behavior and upon the first invocation that behavior will be executed. There are a bunch of examples showing various common use cases, such as an entirely offline installation.

I created this out of frustration with pretty much every other tool that is used to package Python applications into standalone binaries. PyOxidizer came close but in order to make it work I had to either not produce a single binary or drop compiled dependencies (or do a few hacks).

In my view, the age of single binary Python applications is here :smile:

example

14 Likes

Since you have already mentioned pyoxidizer, can you expand upon how pyApp differs from it (and other projects in this space)? I’ve had a quick look at the docs but could not find anything there. A “why pyApp” section that compared it with other projects and what benefits and traffics pyApp has would be really useful.

6 Likes

Configuration - PyApp isn’t the latest stable 3.12? Doesn’t show up here :thinking:

Furthermore, would be nice if the example GIF would demonstrate how this would work on Windows, perhaps a separate GIF? And I’d separate the app builder and the end user GIFs to show the two sides separately, would make it easier to understand. Looks good, though.

The example shows lines “downloading distribution” and “creating virtual environment”. Where are the distribution and virtual environment stored on disk? Can that be altered/configured to create truly standalone applications, that live in a single directory and make no changes to any other directories on the target system? (Obviously this ignores any effect that comes from the application’s Python code itself).

Also, can the download and virtual environment be pre-created, so that the first run of the application doesn’t take that hit? I’m thinking of a situation where you prepare a single directory containing the runnable application, that can then be copied to the target machine and used there without needing internet access, or access to any of the disks on the target machine (apart from the directory the app is installed in).

I think this is what the “Custom embedded local distribution” or “Offline installation” examples are about, but there’s so little information there that I can’t be sure.

1 Like

The most fundamental issue was that Hatch depends on virtualenv and that simply cannot run without access to inspect a Python executable. I asked PyInstaller, Nuitka, and PyOxidizer. It seems like it might have been possible after a few features were added to the latter but even now that has not happened.

Oh I need to update that page, thank you! It is supported.

I’m confused by this because it’s the same process. What do you mean?

That’s a good idea I’ll try that when I have time!

I’ll add this to the docs, thanks!

Platform Path
macOS ~/Library/Application Support/pyapp
Windows %USERPROFILE%\AppData\Local\pyapp
Unix $XDG_DATA_HOME/pyapp (the XDG_DATA_HOME environment variable default is ~/.local/share)

Yes you can configure the location.

No, but technically you can use the option to install directly within the distribution rather than creating a virtual environment and if the path to the unpacked distribution already exists then I believe nothing would happen as you desire.

2 Likes

Hi, is there a way to have a “single binary” with a stripped down virtual env like there is with pyinstaller?

1 Like

… and that can be relative to the application executable? The docs don’t say what a relative pathname would mean here.

I really don’t understand that option at all. An example of how to use it from scratch (for example, a simple “hello, world” app) would be helpful. Actually, an example of a “hello, world” app, and how the various options affect it, would be a great tutorial for the utility.

To be clear, the resulting “application” is a wrapper that embeds a package to install and then does something like what PipX would do, with that embedded package?

Or just what?

I won’t be able to explain any better than this Mermaid diagram I made Runtime behavior - PyApp

1 Like

I’m still not clear, if I have a “hello, world” script, how do I bundle it into a standalone app? I think I need to package my script as a wheel, is that right? And I guess then I run PyApp against that local wheel (I don’t need to upload it to PyPI, hopefully!)

Did you happen to look at the examples? Here is one with a script: Examples - PyApp

Am I missing something? The examples are just lists of environment variables and their values. I don’t understand how they should be used. Maybe I’m being dumb, if so I’m sorry.

The docs could be improved but how to build is the very first page after the About page: Building - PyApp

I see there environment variables and cargo :thinking: do I really need to use those if I’m an end user of an app? I had the impression those are only needed for creating the package by the maintainer of that app :thinking:

1 Like

Definitely not! As I mentioned in the very first post:

Users just run the binary.

For me too, I am not sure where to find the instructions I should type. The only thing I could find is the animation GIF (?), but it goes too fast, I can not pause, and I can not copy-paste. I believe it is in there somewhere but I can not find it.

@ofek I would say the same as I think applies for the hatch documentation, it is too DRY (don’t repeat yourself). Documentation should repeat things… a lot…

5 Likes

PyApp is configured using env vars instead of e.g. a configuration file or CLI options, which is not the most intuitive thing for Windows users. I think I might be the only non-Hatch user of PyApp; see instawow/noxfile.py at 8b973e202b5ecbb0b87d6327cdc9e49cfad4d1bf · layday/instawow · GitHub if it might help.

1 Like

I agree with the improvements to Hatch docs but I don’t see any way to improve this. The first page is the standard About with a short demo. The page immediately after is called Building and says this:

Before building your application, you must configure your project at the very least. After you have done that, your application can be built using a local copy of this repository or via installation with Cargo.

As that page and @layday says, configuration is environment variables.

If we take the local copy approach it says:

After unpacking the repository, enter the directory and run:

cargo build --release

The executable will be located at target/release/pyapp.exe if on Windows or target/release/pyapp otherwise. If a particular target has been set (or when cross compiling since one will always be set), then the release directory will be nested one level deeper under target/<TARGET>.

I don’t know how else to improve this, genuinely. Perhaps make it explicit how to install Cargo? I just don’t know.

I guess one thing is that if I come to pyapp documentation with Python packaging in mind and I am confronted with a whole lot of cargo/rust commands and terminology I have never seen before, it is disconcerting. I guess some tutorial is in order. The documentation seems like just a reference, which is useful when you already know how to use the tool, but not if you want to learn.

I believe the first thing would be to have the commands from the animation as static text one can copy-paste.

Documentation is not easy.

What executable? The pyapp executable that I should use to build my app, or is it my app already? If it is my app why is it named pyapp?

2 Likes

Hence why in my request suggested separating what the maintainer does from what the end user sees and does. Currently they are merged into the same GIF.

4 Likes