8 ms·
Compile Python applications into stand-alone executables
- pacifika 5y agoI’ve tried all the options and my view is unless you test bundling from the start of the project you’re in for a world of hurt, either having to manually patch packages (ntlk); or produce executables that are missing dependencies. It’s the main reason I’m looking at switching to Go for these kinds of apps. Python should have a working solution as part of the standard library.
- amir734jj 5y agoAgreed. Dotnetcore, rust, golang all have an out of the box option for shipping binaries. I really enjoy using python to get something done fast but I'm not a fan of the whole ecosystem.
- KronisLV 5y agoStrongly agreed. Where Python fails is dependency management and packaging, much like this xkcd portrays: https://xkcd.com/1987/ https://xkcd.com/1987/ It's a shame, too, because the language is perhaps one of the easiest to read, write and just generally develop in, and has a really rich ecosystem which can be leveraged to great success. I've felt for a long time that language specs should be more clearly separated from their runtimes. Why couldn't we have statically compiled Python? Why did native Java executables need something like GraalVM be painstakingly introduced over many years, and even then fail to work properly whenever dynamic loading is involved (e.g. Spring framework)? The answer probably lies in the insane complexity all of that involves and making these decoupled isn't feasible with our current tooling, unless we want to spend a decade developing a new language/runtime like that.
- pseudalopex 5y ago> Where Python fails is dependency management and packaging, much like this xkcd portrays: https://xkcd.com/1987/ https://xkcd.com/1987/ Python packaging has its problems. But other languages are confusing if you have 5 or more overlapping versions from 4 sources too. > Why couldn't we have statically compiled Python? We have RPython and Cython.
- arboghast 5y agoDoesn’t allow you to create standalone binaries. Cython requires you to package the Python runtime DLLs (on Windows) otherwise it won’t run.
- tannhaeuser 5y ago> [Java/GraalVM natively compiled apps] fail to work properly whenever dynamic loading is involved (e.g. Spring framework) What do you exactly expect if Spring/Java heads insist on late binding and religously exercise "dependency injection"? You can configure native-image reflection based on a closed-world assumption wrt what classes are known at compile-time, but TBH it seems futile if devs use shit-tonnes of annotation, dynamisms, and reflection magic. Or, as someone else here said, "in idiomatic Java/Spring code, behavior is expressed through anything and everything, except actual Java code."
- KronisLV 5y agoI expect the Spring framework to hopefully some day fade into obscurity and die. Its ample usage of reflection is just evil, polluting your stack traces with needless proxy classes and abstraction upon abstraction upon abstraction. You can debug code pretty easily, whereas doing that with annotations or XML that gets parsed and executed by code that you know nothing about leaves you in hopeless situations more often than you'd like. Instead of solving business problems, you end up solving whatever it is that Spring wants you to do. Thus, most of your post is spot on. Rather often, it is the frameworks that are keeping us in a pretty unhappy place. In contrast, languages like Go feel a bit more pure in that regard, even generics were only added recently. Not giving the framework developers tools to express endless complexity is probably a good idea.
- kissgyorgy 5y agoMy favorite is the fairly new, but excellent PyOxidizer: https://github.com/indygreg/PyOxidizer https://github.com/indygreg/PyOxidizer It's written in rust and can embed resources and dependencies in the executable.
- harelba 5y agopyoxidizer is amazing indeed. Just repackaged my own open source project for multiple platforms using pyoxidizier. I wish it would merge into the python ecosystem itself. Harel https://github.com/harelba https://github.com/harelba
- alex_hirner 5y agoThanks, I'll take your .bzl as inspiration [0]. How did you go about developing against the Starlark API, any IDE support? [0] https://github.com/harelba/q/blob/master/pyoxidizer.bzl https://github.com/harelba/q/blob/master/pyoxidizer.bzl
- jacksonkmarley 5y agoSoon after going through the python environment selection dance (pyenv fwiw, although sometimes conda), I went through the python binary tool selection dance and ended up on pyinstaller. However I eventually abandoned hope that I was on a fruitful path, and changed course for web server land, embarking on the python web framework selection dance.
- dmingod666 5y agoDid you do the Python version selection dance before that though? 2.7/3.6/3.8/3.9 :D
- jacksonkmarley 5y ago2 to 3 did come up at one point, yes. At the time I chose 2 but nothing much came of the choice since I didn't continue with python at the time, and nothing much came from what I was working on either. The updates to 3 have a bit more impact now that I'm doing most of my work in python. Some of the features dropping seem too cool to not update.
- pansa2 5y agoIIRC a big issue with PyInstaller is that the built executables are really self-extracting archives, which have to write many files to disk before they can run. Compared to a real compiled executable, it’s slow and inelegant. Unfortunately high-quality bundling into executables just isn’t a focus of Python (nor of any other high-level language). Personally, I’ve gone back to C++ for building command-line apps - as a developer I’d much rather be writing Python, but that’s no good if I can’t actually deliver software to users.
- ZuLuuuuuu 5y agoI thought that it is the case only when you bundle into "one file"? If you don't pass the --onefile parameter, all files are in one folder without any archiving, am I wrong?
- pansa2 5y agoThat’s right - but if you don’t use `-—onefile` you don’t really have a “stand-alone executable” at all.
- scarygliders 5y agoCorrect. I don't use --onefile at all. I go the old-skool way, and package my python Windows app(s) into an installer using Inno Setup.
- mherrmann 5y agoOf course you have a stand-alone executable. At least if by "stand-alone" you mean a copy you can ship to users. Which is at least the only thing I care about. And tell me which popular (say) Windows software actually comes as a single .exe. They're all many files in multiple folders. And there's no problem with that. You have one installer, which users download, which then extracts the files. Your criticism points out a non-issue.
- dmingod666 5y agoYou also need to make sure to compile the binaries in the OS version that is close to your target deployment version, I remember had RHEL 6.x Vs RHEL 7 issues due to libc or a similar dependency.
- ZuLuuuuuu 5y agoPyInstaller has been a life-saver for our work. The thing with our work is that we heavily use Python and SciPy stack but we also have quite a few GUI stuff. We preferably have all our code base in Python because our team is mostly familiar with Python. Also keeping both the GUI and the application logic in Python makes it super easy to pass around data (usually numpy arrays) which we do all the time. No server/client architecture or marshalling needed when everything is Python. And we are mostly developing internal tools, so the executable size isn't a huge concern. But we still want an executable that can be copied from computer to computer and can be opened via a simple double-click, because not everybody in our company is a software engineer, a lot of people are just used to copying the executable to their computer and double-clicking on it to launch it. We don't use the --onefile feature since it makes the launches slow because of the extraction step. So we have a folder with an executable and the dependencies in it. PyInstaller was a very good fit for our case. Yes the size of the bundle is quite big but it does the job. And allowed us to keep our whole code base in Python.
- mark_l_watson 5y agoYou are fortunate that your apps depend on SciPy for machine learning and not TensorFlow. TensorFlow is not on the list of supported 3rd party libraries, but I think I will try it anyway later today just to see if it works with pyinstaller.
- joconde 5y agoPyTorch works very well with PyInstaller. The only issue is that it can't use the DataLoader's worker processes, they crash for some reason (even with multiprocessing.freeze_support()).
- mark_l_watson 5y agoThanks, good to know!
- anakaine 5y agoThe most recent version of pyinstaller has been flagged in our enterprise fireeye endpoint security default rules. What happens is that pyinstaller has a folder in the python pyinstaller library directory that has 4 exes in it that are used to produce the final exe. One is called run.exe. Fireeye quarantines / deletes these. This didn't happen on older versions. Its a pretty big issue if these are stubs that will be flagged or if they will be compiled in with the final executable such that an application deployed to users might get flagged as malicious.
- Fizzadar 5y agoI use pyinstaller for my Kanmail email client [1] and it’s fantastic, but at creating Mac app bundles or Windows exes. Tried making actual standalone binaries for another project and, as others have mentioned, they’re incredibly slow to startup. Still, I am a huge fan of the project and it makes it possible to make webview desktop “apps” (like or hate them) with Python. [1] https://kanmail.io https://kanmail.io
- mark_l_watson 5y agoThe ability to make self contained executables is important. LispWorks and SBCL Common Lisp make nice, compact executables which opened more use cases for me with those languages. I tried pyinstaller a few years ago, but it does not support some 3rd party libraries like TensorFlow that I frequently use. That said, I like that they clearly list supported 3rd party libraries so it is a quick check if pyinstaller will work for a specific project.
- scarygliders 5y agotip: Rather than using --onefile to create a single standalone executable, IMO you're far better off creating a dist then packaging that into an Installer using Inno Setup or similar. Your app will start quicker, because it won't be a case of the "single executable" doing the old unzip-and-run thing every time.
- randlet 5y agoPy2exe/pyinstaller is what I've always done as well. It works really well for distributing Python apps on Windows in my experience. Have been using that combo for many years now and while it's not perfect it is still the best way to distribute Python applications on Windows.
- ashishknitcs 5y agoIn role of IT manager py2exe and pyinstaller are my goto tool to make script work on machine. I’m from a IT dept of a oil company not much of savvy apps mostly dull. As manager have to do lots of data wrangling for this and that form of reports. scripts to do jobs on machine. Python is only fullstack i know. Pyinstaller is mine goto tool to build executable and make it portable across environment.
- remram 5y agoPSA: If you distribute this kind of software, be ready to deal with many antivirus issues. [1] has helped but it's still a very manual and frustrating process on every release. [1]: https://github.com/hankhank10/false-positive-malware-reporting https://github.com/hankhank10/false-positive-malware-reporti...
- iwalton3 5y agoI have found that a useful way to evade antivirus issues with PyInstaller is to build my own copy of the bootloader and encourage use of the 64 bit version over the 32 bit version (since most malware will use the 32 bit version to infect the most computers). I have a GitHub CI job which is able to automate the process for each release. https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/.github/workflows/main.yml#L24 https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/.g...
- ta988 5y agoI deployed a Py application (Pandas, PyQT) at work. It was horribly slow on half of the Windows machines ,likely because of the antivirus but I didn't have admin rights to check that. It was impossible to make a single file exe because it took too long to decompress. I spent days trying to reduce all the unused files half-manually (because automated approaches kept failing). In the end I threw all of that out , rewrote the UI and deployed it as a web application on a server. Now the users are happy.
- jacksonkmarley 5y ago> I deployed a Py application (Pandas, PyQT) at work ... >In the end I threw all of that out , rewrote the UI and deployed it as a web application on a server. Now the users are happy. This sounds familiar.
- welder 5y agoI really tried to use PyInstaller and Nuitka to deploy a Python command line [1] to Windows, Mac, and Linux users. We couldn't get around some system dependencies like OpenSSL needing to be available and not broken on user machines. We ended up re-writing the whole program from Python into Go [2]. Using Go solved so many long-tail bugs for us and just simplified the whole process of shipping code to user machines. Here's the old but working build script that built both PyInstaller and Nuitka [3]. [1] https://github.com/wakatime/legacy-python-cli/tree/standalone https://github.com/wakatime/legacy-python-cli/tree/standalon... [2] https://github.com/wakatime/wakatime-cli https://github.com/wakatime/wakatime-cli [3] https://github.com/wakatime/legacy-python-cli/blob/standalone/build_standalone.py https://github.com/wakatime/legacy-python-cli/blob/standalon...
- numbsafari 5y agoAnd if you need python-like configurability/reprogrammability, with go, you can use Starlark. https://github.com/bazelbuild/starlark https://github.com/bazelbuild/starlark
- simonh 5y agoMuch as I love Python, there certainly are some corners of the ecosystem like that which have issues. Zip file support is another one where it's fine for many common cases but you don't have to try very hard to hit some niggles. The thing is I don't know if that's particular to Python, or whether every language ecosystem has this but Python is so widely used more people hit these issues.
- fxtentacle 5y agosigh that's not "compiling" as programmers usually use it. PyInstaller merely packages uncompiled python programs into a self-extracting archive. Cython, on the other hand, can truly compile python3 into gcc object files which are then linkable.
- groundthrower 5y agoA huge Corp really wanted our app but not the cloud based SPA app we offered - they wanted “executables” with no data stored in the cloud. Ended up creating a electron app, using our SPA and django packaged with pyinstaller that fires up as a child process. Thus a local backend with SQLIte. It’s now rolled out and works great.
- quietbritishjim 5y agoAlso worth checking out: Nuitka [1]. It actually compiles your Python into machine code (albeit still making use of the CPython interpreter). Despite the title, pyinstaller doesn't really compile anything, it just bundles your bytecode and the interpreter into a binary. That's often useful, but it's not the same thing. You can get similar-ish results to Nuitka by combining pyinstaller with Cython but it's quite a bit of work. [1] https://nuitka.net/ https://nuitka.net/
- deleted 5y ago[deleted]
- dmingod666 5y agoThis sounds much better than pyinstaller. How was your experience with it? Is it straight forward or did you see issues or had to do tweaks to your code to make it work?
- RMPR 5y agoNot OP but my experience trying out nuitka vs PyInstaller on atbswp[0] is nuitka takes significantly longer (and CPU time) to run and in my case the resulting executable wasn't working, it was because I use wxPython or some hidden import in my dependencies, I don't remember exactly. Bottom-line I think nuitka is great if you (or your dependencies) does not do black magic in the imports, otherwise you're in for a lot of debugging. 0: https://github.com/rmpr/atbswp https://github.com/rmpr/atbswp
- quietbritishjim 5y agoSo far I haven't had to make any tweaks to my code, though I don't try to do anything fancy. Getting it to work with dependencies can be a bit trickier, some of them need some Nuitka-specific hacks. The Nuitka creator/maintainer actually maintains a shocking number of these himself, in the form of Nuitka "plugins". It can be hard to figure out the right command line syntax to enable these, which is obviously a small inconvenience compared to creating them in the first place but can still be annoying. So far I've used Qt and numpy plugins and they work well. Trio doesn't work at the moment but support is likely to be coming soon. As one of the top comments for pyinstaller here says, you'll probably be better off if you're using Nuitka from day 1 rather than suddenly using it for a big exclusive project. As with pyinstaller, it has the option to bundle everything into a single file. This is convenient but has the same disadvantage of being a bit wasteful, especially on Windows where it extracts files to the temp directory on every run (as another comment says about pyinstaller). On Linux I think it uses a ramdeive. A very nice feature of Nuitka is a alternative mode where it doesn't put everything into one file. All the pure Python is compiled to a binary but it leaves all the binary dependencies and resources separate, which you can then deploy together in a directory. This is a bit less convenient for users but a bit more efficient and has the very nice property of being LGPL compliant if you're using PyQt/PySide. It's also useful for debugging the single-file mode, since that is really a wrapper around this mode.
- zvr 5y agoRepeating my comment from every time PyInstaller is being discussed: One issue with PyInstaller is that, by default, it includes all dynamic libraries that the Python interpreter has on your machine. It makes sense, it needs an interpreter and collects what is needed for it to run. Unfortunately this might include libreadline.so, which is licensed under GPL, making your resulting executable unable to be distributed under a proprietary license. There are ways to solve this issue, but one has to search and read documentation (and code, in my case -- when I was researching it, the docs were not clear).