I have a hello world flask app ```import os from...
# general
p
I have a hello world flask app
Copy code
import os

from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello_world():
    """Example Hello World route."""
    name = os.environ.get("NAME", "World")
    return f"Hello {name}!"


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Located at
src/python/playground/hello_cloud_run/main.py
I can run it with
pants run src/python/playground/hello_cloud_run/main.py
When I add a pex_binary...
Copy code
python_sources(name="lib")

pex_binary(name="hello_cloud_run", entry_point="main.py")
If I go to run the pex_binary I see..
Copy code
pants run src/python/playground/hello_cloud_run:hello_cloud_run
 * Serving Flask app 'main' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.
 * Running on <http://192.168.1.33:8080/> (Press CTRL+C to quit)
 * Restarting with stat
/home/geethree/.pyenv/versions/3.9.18/bin/python3.9: Error while finding module specification for 'playground.hello_cloud_run.main' (ModuleNotFoundError: No module named 'playground')
I do have an init.py and BUILD located at src/python/playground.
Any advice?
A source.root_pattern is
/src/python
When poking around in the unzipped pex binary I see..
Copy code
dist/src.python.playground.hello_cloud_run$ tree -L 3 pex/
pex/
├── __main__.py
├── __pex__
│   └── __init__.py
├── PEX-INFO
└── playground
    ├── hello_cloud_run
    │   ├── __init__.py
    │   └── main.py
    └── __init__.py
Hmm this has to do with the
use_reloader
option that debug option of flask.run sets in werkzeug.. https://werkzeug.palletsprojects.com/en/2.3.x/serving/#werkzeug.serving.run_simple
g
Can you throw up a GitHub repo with this example?
h
Actually sorry, that is a related issue (the auto-reloader) but I have also seen what you're seeing here with Django, it has to do with the re-exec, but I forget the details
See here for the difference in semantics between running a file and running a pex
Does the pex binary work if you package it and then execute it directly (rather than via
pants run
)?
My memory is hazy, but I recall this has something to do with the fact that the reloader in Django's development server (and I guess Flask's) makes some assumptions that don't hold in a sandbox
d
I’ve done a lot of pants/flask and tried to reproduce this one (Flask 3.0.2 and pants 2.19.1 Typically I’d do something like:
Copy code
pex_binary(
    name="flask",
    entry_point="flask",
    args=["--app", "app.py"],
)
Instead of running the script pointing at main.
Copy code
pants run :flask -- run --debug
Or something like:
Copy code
pex_binary(
    name="flask",
    entry_point="flask",
    args=["--env-file", ".env"],
    dependencies=["app.py", "//:root#python-dotenv"],
)
To load configuration from
.env
with
python-dotenv
g
I actually had similar problems and I just ended up creating a bunch of pex binaries with different entry point. Then finally landed on creating a single virtual environment and using traditional VIRTUALENV + PATH to execute what I needed. I would just add explicit deps that weren’t imported, e.g. gunicorn, datadog, etc
For first party things I created simple python scripts and copied them into place. I wish there was a first class way to do this automatically.