Search code examples
pythonflaskquartflask-caching

Importing a Flask extension in Quart using Blueprints


I am currently building a basic application in which I am carrying out measurements with a sensor connected to the hosting Raspberry Pi. To do so, I have decided to go for Quart, as it allows me to run them in the background. I am currently trying to use the cache such that the data can be used by the JS frontend (eg. for downloading, live plotting) through eg. websockets and by other requests. I want to do this with the extension Flask-Caching, which is supported by Quart according to pgjones. However, once I try to initialize the extensions, I get

Traceback (most recent call last):
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/bin/quart", line 8, in <module>
    sys.exit(main())
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/quart/cli.py", line 344, in main
    cli.main(args=args, prog_name=name)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/quart/cli.py", line 235, in main
    return super().main(*args, **kwargs)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/click/core.py", line 1653, in invoke
    cmd_name, cmd, args = self.resolve_command(ctx, args)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/click/core.py", line 1700, in resolve_command
    cmd = self.get_command(ctx, cmd_name)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/quart/cli.py", line 220, in get_command
    command = info.load_app().cli.get_command(ctx, name)  # type: ignore
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/quart/cli.py", line 72, in load_app
    module = import_module(import_name)
  File "/home/andromedan/anaconda3/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/run.py", line 7, in <module>
    app = create_app()
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/app/__init__.py", line 15, in create_app
    cache.init_app(app, config=config.CACHE)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/flask_caching/__init__.py", line 220, in init_app
    self._set_cache(app, config)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/flask_caching/__init__.py", line 251, in _set_cache
    app.extensions["cache"][self] = cache_factory(
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/flask_caching/backends/filesystemcache.py", line 95, in factory
    return cls(*args, **kwargs)
  File "/home/andromedan/kubo_sound/webapp/kubo_masking/venv/lib/python3.8/site-packages/flask_caching/backends/filesystemcache.py", line 76, in __init__
    os.makedirs(self._path)
  File "/home/andromedan/anaconda3/lib/python3.8/os.py", line 208, in makedirs
    head, tail = path.split(name)
  File "/home/andromedan/anaconda3/lib/python3.8/posixpath.py", line 103, in split
    p = os.fspath(p)
TypeError: expected str, bytes or os.PathLike object, not NoneType

tracing back to the line

cache.init_app(app, config=config.CACHE)

in my app factory. This is the app factory

import quart.flask_patch

from quart import Quart
from config import Config

# import extensions instance
from flask_caching import Cache

cache = Cache()

def create_app(config=Config):
    app = Quart(__name__)
    app.config.from_object(config)

    # initialize extension instances
    cache.init_app(app, config=config.CACHE)
    
    # register blueprints of applications
    from app.main import main as main_bp
    app.register_blueprint(main_bp)

    from app.measurement import measurement as measurement_bp
    app.register_blueprint(measurement_bp)

    return app

and runfile code

# import the create app application factory
from app import create_app

# import the application config classes
from config import Config

app = create_app()

if __name__ == '__main__':
app.run()

The CACHE attribute Config is given by the dictionary {'CACHE_TYPE': 'FileSystemCache'}.

I have tried other options such as cache = Cache(app, config=config.CACHE) to initialize the extension, none of them worked...

Bonus Question: What is the difference between the cache types mentioned in the flask docs?

Thank you!


Solution

  • The CACHE attribute in the Config is missing CACHE_DIR, which will define where the FileSystemCache stores cached data. For example, if the CACHE attribute Config was the dictionary {'CACHE_TYPE': 'FileSystemCache', 'CACHE_DIR': '/tmp'}