[英]Declare python module in yaml
我有一個 yaml 文件,其中有一些字段的值在 python 中是可以理解的,但是它們被解析為字符串值,而不是我的意思是 python 類型。 這是我的樣本:
verbose:
level: logging.DEBUG
很明顯,當我加載它時,該值是字符串類型
config = yaml.load(args.config.read(), Loader=yaml.SafeLoader)
我不知道如何准確獲取logging.DEBUG
對象,而不是它的字符串。
請注意,我不尋找配置日志來獲取記錄器的東西。 此日志記錄只是 python 模塊的一個示例。
沒有開箱即用的方法。 最簡單和最安全的方法似乎是手動處理值,例如:
import logging
class KnownModules:
logging = logging
...
def parse_value(s):
v = KnownModules
for p in s.split('.'):
v = getattr(v, p) # remember to handle AttributeError
return v
但是,如果您可以稍微更改 YAML 結構,PyYAML 支持一些自定義 YAML 標簽。 例如:
verbose:
level: !!python/name:logging.DEBUG
將使config['verbose']['level']
等於logging.DEBUG
(即10
)。
考慮到您(正確)使用SafeLoader
,您可能需要通過定義自己的標簽來組合這些方法。
編輯:請參閱 AKX 答案。 我不知道logging._nameToLevel
不需要定義自己的 enum 並且絕對比使用evel
更好。 但是,我決定不刪除此答案,因為我認為使用枚舉的當前首選設計(從 python 3.4 開始)值得一提(如果當時可用,它可能會在日志記錄模塊中使用)。
如果您絕對確定配置中提供的值是合法的,您可以像這樣使用eval
:
import logging
levelStr = 'logging.DEBUG'
level = eval(levelStr)
但正如評論中所說,如果您不確定配置文件中存在的值,使用eval
可能是災難性的(請參閱 AKX 在評論中提供的示例)。
更好的設計是為此目的定義一個枚舉。 不幸的是,日志模塊不提供枚舉級別(它們只是模塊中定義的常量),因此您應該定義自己的級別。
from enum import Enum
class LogLevel(Enum):
CRITICAL = 50
FATAL = 50
ERROR = 40
WARNING = 30
WARN = 30
INFO = 20
DEBUG = 10
NOTSET = 0
然后你可以像這樣使用它:
levelStr = 'DEBUG'
levelInt = LogLevel[levelStr].value # Comparable with logging.DEBUG which is also an integer
但是要使用它,您必須稍微更改 yml 文件並將logging.DEBUG
替換為DEBUG
。
YAML 加載器不知道logging.DEBUG
可能意味着什么,除了字符串"logging.DEBUG"
(除非它被標記為 YAML 標簽)。
對於需要解釋為例如對模塊屬性的引用的字符串值,您需要事后解析它們,例如
def parse_logging_level(level_string: str):
module, _, value = level_string.partition(".")
assert module == "logging"
return logging._nameToLevel[value]
# ...
yaml_data["verbose"]["level"] = parse_logging_level(yaml_data["verbose"]["level"])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.