I'm new with using flask so I'm doing a lot of research to find out what the best way to structure my application. I've been following app factories and using blueprints, but I'm having trouble figuring out how to use application wide libraries and keep the app context. For example here is my app structure:
├── app
│ ├── acuity
│ │ ├── handlers.py
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── config.py
│ ├── __init__.py
│ ├── logs
│ ├── main
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── slackapi.py
│ └── templates
│ └── acuity
│ └── acuity_slack.j2
├── gunicorn_config.py
├── slackbot.py
├── README.md
└── requirements.txt
Main and Acuity are blueprints. Main doesn't do anything and the only endpoints are in acuity. In acuity.handlers I'm importing in app.slackapi but can't use current_app no matter how I slice it. I need to use the app context in order to access the logging and config vars.
What's the best way to put the slackapi and any other common utility functions or common libraries I make into the global flask context so that I can use them inside of any of the blueprints?
EDIT: This is how I'm importing from acuity.handlers
import dateutil.parser, datetime, os, json, requests
from jinja2 import Environment, FileSystemLoader
import app.slackapi as slack
from flask import current_app
If I try to from flask import current_app
in app.slackapi it doesn't error. But if I try to use and reference current_app like this:
import time
from slackclient import SlackClient
from flask import current_app
# instantiate Slack client
slack_client = SlackClient(current_app['SLACK_API_TOKEN'])
This error arises
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/workers/base.py", line 129, in init_process
self.load_wsgi()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/workers/base.py", line 138, in load_wsgi
self.wsgi = self.app.wsgi()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/app/wsgiapp.py", line 52, in load
return self.load_wsgiapp()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
return util.import_app(self.app_uri)
File "/usr/local/lib/python3.5/dist-packages/gunicorn/util.py", line 350, in import_app
__import__(module)
File "/opt/slackbot/slackbot/slackbot.py", line 3, in <module>
app = create_app()
File "/opt/slackbot/slackbot/app/__init__.py", line 22, in create_app
from app.acuity import bp as acuity_bp
File "/opt/slackbot/slackbot/app/acuity/__init__.py", line 5, in <module>
from app.acuity import routes
File "/opt/slackbot/slackbot/app/acuity/routes.py", line 4, in <module>
from app.acuity import handlers
File "/opt/slackbot/slackbot/app/acuity/handlers.py", line 3, in <module>
import app.slackapi as slack
File "/opt/slackbot/slackbot/app/slackapi.py", line 10, in <module>
slack_client = SlackClient(current_app['SLACK_API_TOKEN'])
File "/usr/local/lib/python3.5/dist-packages/werkzeug/local.py", line 377, in <lambda>
__getitem__ = lambda x, i: x._get_current_object()[i]
File "/usr/local/lib/python3.5/dist-packages/werkzeug/local.py", line 306, in _get_current_object
return self.__local()
File "/usr/local/lib/python3.5/dist-packages/flask/globals.py", line 51, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
EDIT TWO:
app/__init__.py
import logging
from logging.handlers import RotatingFileHandler
import os
from flask import Flask, request, current_app
from config import Config
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
from app.main import bp as main_bp
app.register_blueprint(main_bp)
from app.acuity import bp as acuity_bp
app.register_blueprint(acuity_bp)
if not app.debug and not app.testing:
if app.config['LOG_TO_STDOUT'] == "True":
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
app.logger.addHandler(stream_handler)
else:
if not os.path.exists(os.path.dirname(__file__) + '/logs'):
os.mkdir(os.path.dirname(__file__) + '/logs')
file_handler = RotatingFileHandler(os.path.dirname(__file__) + '/logs/slackbot.log',
maxBytes=10240, backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Slackbot startup')
return app
app/acuity/__init__.py
from flask import Blueprint
bp = Blueprint('acuity', __name__)
from app.acuity import routes