Search code examples
pythonflaskglobalwsgi

Flask, WSGI, and Global Variables to Hold Database Pool


I'm using WSGI/Apache2 and am trying to declare my database pool on init, to be accessible via a global var from my endpoints. I'm using Redis and Cassandra (DSE, specifically). It's my understanding that both the Redis and DSE libs offer pool management so this shouldn't be an issue.

My folder structure for my WSGI app looks something akin to

folder/
    tp.wsgi
    app/
        __init__.py
        decorators/
            cooldec.py
        mod_api/
            controllers.py

tp.wsgi looks like the following

#! /usr/bin/env python2.7

import sys
import logging

logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/opt/tp")

from app import app

def application(environ, start_response):
    return app(environ, start_response)

__init__.py looks like the following

#! /usr/bin/env python2.7

from flask import Flask
from cassandra.cluster import Cluster

# Import our handlers
from app.mod_api.files import mod_files

# Setup routine 
def setup():

    # Instantiate Flask
    app                     =       Flask('app')

    # Set up a connection to Cassandra
    cassandraSession = Cluster(['an ip address', 'an ip address']).connect('keyspace')
    cassandraSession.default_timeout = None 

    # Register our blueprints  
    app.register_blueprint(mod_files)
    ...

    return app, cassandraSession

app, cassandraSession = setup()

I'm calling a decorator defined in cooldec.py that handles authentication (I use that term loosely, for a reason. I ask that we not go down the path of using Flask extensions for authentication, that's out of scope for this question and isn't applicable in my use-use [see: loose usage of the term 'authentication'])

In cooldec.py and controllers.py I'm trying to access the cassandraSession global but I keep getting global name 'cassandraSession' is not defined. I know what the error means, but I'm not sure why I'm seeing this. It's my understanding that the way I've set my WSGI app up allows for cassandraSession to be accessible within the scope of the app, no?

I found Preserving state in mod_wsgi Flask application but .. it hasn't really shed any light on to what I'm doing wrong.


Solution

  • My issue was the location of my imports. I made a few changes to tp.wsgi and __init__.py and I've got what I need working. That is, calling from app import cassandraSession from within cooldec.py and controllers.py

    Below is how I've set up the aforementioned.

    tp.wsgi

    #! /usr/bin/env python2.7
    
    import sys
    import logging
    
    logging.basicConfig(stream=sys.stderr)
    sys.path.insert(0, "/opt/tp")
    
    from app import app as application
    

    __init__.py

    #! /usr/bin/env python2.7
    
    # API Module
    
    from flask import Flask, jsonify
    from cassandra.cluster import Cluster
    
    # Create our API
    app                     =       Flask('app')
    
    # Define a cassandra cluster/session we can use
    cassandraSession = Cluster(['an ip address' 'an ip address']).connect('keyspace')
    cassandraSession.default_timeout = None
    
    ... Register blueprints
    

    These are overly simplified edits, but it gives the idea of what I was doing wrong (eg: declaring in wrong file and trying to import improperly.

    In both cooldec.py and controllres.py we can now do

    from app import cassandraSession
    rows = cassandraSession.execute('select * from table')
    

    Tip for new WSGI developers: Continue to think "in python".

    + WARNING +

    I have yet to find an absolute answer on whether or not this is safe to do. Doing this using sqlalchemy is perfectly OK due to how sqlalchemy handles connection pooling. I am, as of yet, unaware if this is safe to do with Cassandra/DSE, so proceed with caution if you utilize this post.