Search code examples
pythonflaskglobal-variables

Instantiate classes used in Flask routes at runtime


It seems to be pretty common practice to have global scope class instances that are used in flask routes, something like this:

from flask import Flask

app = Flask(__name__)

class Utility:
    def get_properties():
       pass

util_obj = Utility()

@app.route('/aaa/bbb/ccc',methods=['POST'])
def func1():
  util_obj.get_properties()
  pass

if __name__ == "__main__":
    app.run(host='127.0.0.1', port=5000, debug=True)

But what if the Utility class has attributes that need to be instantiated at runtime?

import argparse
from flask import Flask

app = Flask(__name__)

class Utility:
    def __init__(self, x): # x is only known at runtime
        self.x = x
    def get_properties(self):
       pass

util_obj = Utility() # This will fail, as we need "x"

@app.route('/aaa/bbb/ccc',methods=['POST'])
def func1():
  util_obj.get_properties()
  pass

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("x") # This needs to be used to instantiate the Utility class
    app.run(host='127.0.0.1', port=5000, debug=True)

How can this be done cleanly?

I have tried to create a function that creates the app and instantiates the class, but that feels like bad practice.


Solution

  • It sounds like what you are likely after is the application context

    https://flask.palletsprojects.com/en/2.3.x/appcontext/

    Or sessions

    https://flask.palletsprojects.com/en/2.3.x/quickstart/#sessions

    Both of these are useful for storing data and/or returning objects at runtime. The application context in particular is used in the Flask documentation to initialise databases and return their cursor/handle at runtime. I would follow the Flask documentation quickstart and tutorials for a thorough explanation of how to setup a project this way.

    Using what you have there though, you could just set self.x to a default value and change it before initialising your application.

    import argparse
    from flask import Flask
    
    app = Flask(__name__)
    
    class Utility:
        def __init__(self): # x is only known at runtime
            self.x = None
        def get_properties(self):
           pass
    
    util_obj = Utility() # This will fail, as we need "x"
    
    @app.route('/aaa/bbb/ccc',methods=['POST'])
    def func1():
      util_obj.get_properties()
      pass
    
    if __name__ == "__main__":
        parser = argparse.ArgumentParser()
        parser.add_argument("x") # This needs to be used to instantiate the Utility class
        args = parser.parse_args()
        util_obj.x = args.x
        app.run(host='127.0.0.1', port=5000, debug=True)