0

I'm trying to run Flask from an imported module (creating a wrapper using decorators).

Basically I have:

app.py:

import mywrapper

@mywrapper.entrypoint
def test():
    print("HEYO!")

mywrapper.py

from flask import Flask

ENTRYPOINT = None

app = Flask(__name__)

@app.route("/")
def listen():
    """Start the model API service"""
    ENTRYPOINT()


def entrypoint(f):
    global ENTRYPOINT
    ENTRYPOINT = f
    return f

FLASK_APP=app

Running python -m flask, however, results in:

flask.cli.NoAppException: Failed to find Flask application or factory in module "app". Use "FLASK_APP=app:name to specify one.


Is there any trick to getting Flask to run like this? Or is it just not possible? The purpose of this is to abstract Flask away in this situation.

In my head flask should try to import mywrapper.py, which imports app.py which should generate the app and route, yet this doesn't seem to be what occurs.

Any help would be appreciated.

3
  • Did you set the FLASK_APP environment variable as advised in the error message? Commented Jun 4, 2019 at 10:49
  • It's non-obvious what to set it to. I currently have tried both app and app.py. Specifying a factory isn't what I want, because the app is never actually generated in app.py. Taking inspiration from another question that's appeared on the side, I have found that using from mywrapper import * works. So this seems to be a case of Flask not detecting the app if it's not namespaced into the target run module. I want to find a way around this. Commented Jun 4, 2019 at 10:54
  • To add. Simply adding app = mywrapper.app into app.py makes this work... Is there no way around requiring this line? Commented Jun 4, 2019 at 10:55

1 Answer 1

1

So I've since learnt that Flask searches only in the chosen module's namespace for a variable containing a Flask object.

There may be a smart way to avoid this limitation, but I instead decided that it was more sensible to instead just wrap the Flask class itself. If people want direct Flask functionality, I don't really care in this situation, so the only real limitation I have from this is some function names are off limits.

Basically:

wrapper.py:

class Wrapper(Flask):
    def __init__(self, name):
        super().__init__(name)
        self.entrypoint_func = None

        @self.route("/")
        def listen():
            return self.entrypoint_func()

    def entrypoint(self, f):
        assert self.entrypoint_func is None, "Entrypoint can only be set once"

        self.entrypoint_func = f
        return f

and app.py:

from mywrapper import Wrapper

app = Wrapper(__name__)

@app.entrypoint
def test():
    print("HEYO!")
    return "SUCCESS"

This is still abstracted enough that I am happy with the results.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.