从Python日志记录的YAML配置文件中评估语句

Kit*_*Kit 3 python logging yaml

考虑以下Python loggingYAML配置文件片段:

version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  logfile:
    class: logging.handlers.TimedRotatingFileHandler
    level: DEBUG
    filename: some_fancy_import_name.generate_filename_called_error
    backupCount: 5
    formatter: simple
Run Code Online (Sandbox Code Playgroud)

我想以这种方式加载此YAML配置文件:

with open('logging.yaml', 'r') as fd:
    config = yaml.safe_load(fd.read())
logging.config.dictConfig(config)
Run Code Online (Sandbox Code Playgroud)

采取的特别通知filename到的handler应该写日志。在普通的Python代码中,我希望some_fancy_import_name.generate_filename_called_errorlog生成字符串'error.log'。总而言之,我想说这个日志处理程序应该写入'error.log'当前目录中的文件。

但是,事实证明并非如此。当我查看当前目录时,我看到一个名为'some_fancy_import_name.generate_filename_called_errorlog'

为什么要经历所有这些麻烦?

我想filename以编程方式确定。我已成功尝试使用常规Python脚本通过以下方式配置日志记录:

# fancy import name
from os import environ as env

# Programmatically determine filename path
log_location = env.get('OPENSHIFT_LOG_DIR', '.')
log_filename = os.path.join(log_location, 'error')
handler = logging.handlers.TimedRotatingFileHandler(log_filename)
Run Code Online (Sandbox Code Playgroud)

看看如何 log_filename从环境变量中推断出路径。

我想将其转换为YAML配置文件。可能吗?

也许我可能需要通过挖掘dict所产生yaml.safe_load(fd.read()),并做一些eval()东西?

fly*_*lyx 5

您可以添加一个自定义构造函数,并使用特殊标记标记该值,以便在加载它时执行您的构造函数:

import yaml

def eval_constructor(loader, node):
  return eval(loader.construct_scalar(node))

yaml.add_constructor(u'!eval', eval_constructor)

some_value = '123'

config = yaml.load("""
version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  logfile:
    class: logging.handlers.TimedRotatingFileHandler
    level: DEBUG
    filename: !eval some_value
    backupCount: 5
    formatter: simple
""")

print config['handlers']['logfile']['filename']
Run Code Online (Sandbox Code Playgroud)

这会打印出来123,因为该值some_value具有标记!eval,因此已加载eval_constructor

请注意eval配置数据的安全隐患。可以通过将任意Python代码写入YAML文件来执行!