However, to address the other part of your comment, pipx works quite well for installing command line applications.
However, to address the other part of your comment, pipx works quite well for installing command line applications.
Pyinstaller is pretty good for if you need a standalone installer.
Because simple is better than complex. I'd rather download a binary than download a binary + dependencies + set them up + bookkeep for when I want to delete all those files.
> Pyinstaller is pretty good for if you need a standalone installer.
PyInstaller doesn't work for many edge cases. If you're using a Python package that uses a compiled binary written in another language, good luck on your way down the rabbit hole of PyInstaller config. I personally could not succeed in packaging a uvicorn app, for example.
I kinda did managed to run a fastapi with uvicorn and pyinstaller. And I did nothing special
I just took the example app from uvicorn.org:
# main.py
import uvicorn
async def app(scope, receive, send):
assert scope['type'] == 'http'
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/plain'],
],
})
await send({
'type': 'http.response.body',
'body': b'Hello, world!',
})
if __name__ == '__main__':
uvicorn.run('main:app', port=5000, log_level="info")
And ran "pyinstaller --onefile main.py" on it. The resulting binary, when executed, just says: Error loading ASGI app. Could not import module "main".
Please share what exactly did you do that made it work. I already assume it's far from "nothing special"... from src.webserver import app
import uvicorn
if __name__ == '__main__':
uvicorn.run(
app,
host='0.0.0.0',
port=8080,
)
#webserver from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def home():
return {
"home": True
}
@app.on_event("startup")
async def startup_event():
import webbrowser
ip_address = "http://localhost:8080/"
webbrowser.open(ip_address)
#create a python file for pyinstaller import PyInstaller.__main__
if __name__ == '__main__':
name = "test"
pyinstaller_list = [
'main.py',
f'--name={name}',
'--clean',
'--onefile',
]
PyInstaller.__main__.run(pyinstaller_list)
I remember reading this part 'main:app' where you should import the app instead for pyinstaller.This is a github issue where I discussed my original issue with PyInstaller devs - the dev explained the situation very well: https://github.com/pyinstaller/pyinstaller/issues/6362
Because sometimes I just want to write `my_program | your_program` without learning how to install and set up a program in a language I don't personally use, particularly when that language has the worst packaging ecosystem of any mainstream language.