То, насколько вы хотите, чтобы ваши сообщения об ошибках были дружественными, если функция вызывается до ее настройки.
Наименее дружественным является не делать ничего лишнего, и позволить функциям сбои с шумом при AttributeError
s, IndexError
s и т. Д.
Наиболее дружественным было бы иметь функции-заглушки, которые вызывают информационное исключение, такое как пользовательский ConfigError: configuration not initialized
. Когда вызывается функция ConfigParser()
, она может заменить функции-заглушки реальными функциями. Примерно так:
config.py
----------
class ConfigError(Exception):
"configuration errors"
def query_data():
raise ConfigError("parse_config() has not been called")
def _query_data():
do_actual_work()
def parse_config(config_file):
load_file(config_file)
if failure:
raise ConfigError("bad file")
all_objects = globals()
for name in ('query_data', ):
working_func = all_objects['_'+name]
all_objects[name] = working_func
Если у вас очень много функций, вы можете добавить декораторы для отслеживания имен функций, но это ответ на другой вопрос. ;)
Хорошо, я не удержался - вот версия для декоратора, которая значительно облегчает реализацию моего решения:
class ConfigError(Exception):
"various configuration errors"
class NeedsConfig(object):
def __init__(self, module_namespace):
self._namespace = module_namespace
self._functions = dict()
def __call__(self, func):
self._functions[func.__name__] = func
return self._stub
@staticmethod
def _stub(*args, **kwargs):
raise ConfigError("parseconfig() needs to be called first")
def go_live(self):
for name, func in self._functions.items():
self._namespace[name] = func
И примерный прогон:
needs_parseconfig = NeedsConfig(globals())
@needs_parseconfig
def query_data():
print "got some data!"
@needs_parseconfig
def set_data():
print "set the data!"
def okay():
print "Okay!"
def parse_config(somefile):
needs_parseconfig.go_live()
try:
query_data()
except ConfigError, e:
print e
try:
set_data()
except ConfigError, e:
print e
try:
okay()
except:
print "this shouldn't happen!"
raise
parse_config('config_file')
query_data()
set_data()
okay()
и результаты:
parseconfig() needs to be called first
parseconfig() needs to be called first
Okay!
got some data!
set the data!
Okay!
Как вы можете видеть, декоратор работает, запоминая функции, которые он декорирует, и вместо возврата декорированной функции он возвращает простую заглушку, которая вызывает ConfigError
, если он когда-либо вызывается. Когда вызывается подпрограмма parse_config()
, необходимо вызвать метод go_live()
, который заменит все заглушки, вызывающие ошибки, на фактические запомненные функции.