在YAML中执行算术运算?

33
有时我必须在配置文件中指定时间(以秒为单位),但编写确切的秒数很烦人 - 相反,我希望能够执行算术运算,这样我就可以使用:
some_time: 1 * 24 * 60 * 60

而不是精确的:

some_time: 86400

不幸的是,在使用这行代码时:some_time: 1 * 24 * 60 * 60,它会将该配置行视为字符串。当然,我可以使用 - eval(config['some_time']),但我想知道是否可以在 YAML 中执行算术运算?

3个回答

19

我认为没有。至少在规范上是没有的 (http://yaml.org/spec/1.2/spec.html)。人们向yaml添加非官方标签(维基百科似乎提到了一个yield标签的提案,但他们没有说是谁提出的或者在哪里:http://en.wikipedia.org/wiki/YAML#cite_note-16),但似乎没有像你所需的那样的东西可用于pyyaml。

查看pyyaml特定标签,似乎没有什么有趣的东西。尽管!!timestamp '2014-08-26'在某些情况下可能很方便 (http://pyyaml.org/wiki/PythonTagScheme)。


9

可以通过使用PyYAML提供的Python特定标签来实现,即:

!!python/object/apply:eval [ 1 * 24 * 60 * 60 ]

如下所示:
In [1]: import yaml                                                                                                                             

In [2]: yaml.load("!!python/object/apply:eval [ 1 * 24 * 60 * 60 ]")                                                                            
Out[2]: 86400

这自然与执行 eval(config['some_time']) 相同,但它可以省去在程序中明确处理它的步骤。


Python3错误:ConstructorError:在构造Python实例时 期望一个类,但发现<class 'builtin_function_or_method'> 在“<unicode string>”,第1行,第1列: !!python/object/apply:eval [ 1 * ... - dashesy
1
从配置文件中输入eval非常危险。除非是为了个人使用,请不要这样做。 - Can H. Tartanoglu
如果可能的话,始终优先选择像ast.literal_eval这样的东西,即评估Python字面量,而不是任意表达式。 - creanion
我想象这在任何“安全”的yaml加载方法中都不会起作用。 - undefined

0

我曾经尝试过寻找一种方法来解决这个问题,但是没有成功。不过,我使用了以下方法来解决它:

import yaml
from box import Box

file = """
data:
    train_size: 100**2
    test_size: 10**2
"""

config = Box(yaml.safe_load(file))
tr_size = eval(config.data.train_size)
# 100**2 -> 10000
ts_size = eval(config.data.test_size)
# 10**2 -> 100

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接