Inconsistent logging when importing config
MarSoft opened this issue · comments
There is something strange with config import problems handling.
When you specify a non-existing module, you get a message stating Error importing <modulename>
(detailed since #32). When you have some imports problem within your config module, you get the same message.
At the same time, when there is some other error (like SyntaxError
or whatever), it is just thrown immediately.
Also, logging actual error message is postponed to application start; but sometimes initialization of other application components depend on some config values, and will fail when config is no provided. Example:Rework Application.__init__
so that logging can be done
from muffin import Application
from redis import Redis
app = Application('test', CONFIG='no_such_config_module')
redis = Redis(app.cfg.REDIS_URL)
This example will yield AttributeError
about missing REDIS_URL
, without any notice that it could not find a config module. This is misleading.
So there are two improvements I would like to suggest, or alternatively one simplification:
- When handling
ImportError
inApplication.cfg
, check thatexc.name
matchesmodule
and just reraise exception otherwise. This will disable special processing whenImportError
happened inside of configuration hierarchy. - Change postponed logging to fire before returning from
Application.__init__
, not after initialization of the rest of application. - Alternative way is to just abandon special processing of configuration
ImportError
s, because if user provided wrong configuration value then the app is unlikely to work fine, and explicit ImportError from config loading routine looks more adequate for me than (semi-)silent ignoring such errors.
Or, as a modification of 3rd way, we can catch ImportError and re-throw it with altered message to make it obvious that problem is config-related:
try:
module = import_module(module)
config.update...
except ImportError as exc:
raise ImportError('Failed to load config module %s' % module) from exc
In such way, the user will see both original ImportError and a notification that it is config-related:
$ muffin app1
ERROR:root:Error loading configuration module no_such_module
Traceback (most recent call last):
File "/home/mars/opensource/muffin/muffin/app.py", line 130, in cfg
module = import_module(module)
File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 986, in _gcd_import
File "<frozen importlib._bootstrap>", line 969, in _find_and_load
File "<frozen importlib._bootstrap>", line 956, in _find_and_load_unlocked
ImportError: No module named 'no_such_module'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/mars/opensource/muffin/muffin/manage.py", line 271, in run
app = import_app(app_uri)
File "/home/mars/pebble/PebWare/env/lib/python3.5/site-packages/gunicorn/util.py", line 357, in import_app
__import__(module)
File "/tmp/app1.py", line 4, in <module>
app = Application('test', CONFIG='no_such_module')
File "/home/mars/opensource/muffin/muffin/app.py", line 79, in __init__
self.cfg.update(OPTIONS)
File "/home/mars/pebble/PebWare/env/lib/python3.5/site-packages/cached_property.py", line 26, in __get__
value = obj.__dict__[self.func.__name__] = self.func(obj)
File "/home/mars/opensource/muffin/muffin/app.py", line 137, in cfg
raise ImportError('Error loading configuration module %s' % module) from exc
ImportError: Error loading configuration module no_such_module