Python YAML参数引用(从其他参数获取值)(Python YAML parameter reference (get value from other parameter))
我试图在我的Python脚本中使用YAML配置文件,我发现的一个问题是我无法访问其他属性,所以我需要复制很多内容。
例如
root_path: /root
script_path: root_path + /scripts
这当然不存在,但有没有办法实现这一目标? 因为有很多内容我无法复制,因为当一个更改时,我需要在任何地方更改它...
我还研究了创建自己的连接函数
root_path: &ROOT /root
script_path: !join [*ROOT, '/scripts']
def join(loader, node):
seq = loader.construct_sequence(node)
return ''.join([str(i) for i in seq])
yaml.add_constructor('!join', join)
但我每次都需要设置一个&VARNAME ,自动将参数键设置为可引用对象会很好...
I'm trying to use a YAML config file in my Python script, one of the problems I've found is that I can't access other attributes, so I need to duplicate a lot of content.
For example
root_path: /root
script_path: root_path + /scripts
This doesn't exists of course, but is there some way to achieve this? Because there are a lot of contents that I can't duplicate because when one changes, I need to change it everywhere...
I've also looked at creating my own join function
root_path: &ROOT /root
script_path: !join [*ROOT, '/scripts']
def join(loader, node):
seq = loader.construct_sequence(node)
return ''.join([str(i) for i in seq])
yaml.add_constructor('!join', join)
But I need to set a &VARNAME every time, it would be nice to automatically set the parameter key as the referenceable object...
原文:https://stackoverflow.com/questions/30918491
更新时间:2019-12-04 15:23
最满意答案
好吧,我一直在研究解决方案,因为没有什么是我想要的,一切都是如此复杂,我想死...
此解决方案将%something% string转换为something值的值。
它很完美,这是一个例子
root_path: /root
script_path: "%root%/scripts"
使用此方法, script_path将成为/root/scripts 。
def replace_values(yaml_file):
def _get(dict, list):
return reduce(lambda d, k: d[k], list, dict)
def _replace(obj):
for k, v in obj.iteritems():
if isinstance(v, dict):
_replace(v)
if isinstance(v, str):
match = re.match(r'%(.*)%', v)
if match:
reference = match.group(1).split('.')
replace = _get(yaml_file, reference)
obj[k] = re.sub(r'%.*%', replace, v)
_replace(yaml_file)
return yaml_file
用法很简单,只需正常加载Yaml文件,并调用replace。
with open(config_file.get(options.env), 'r') as ymlfile:
config = yaml.load(ymlfile)
config = replace_values(config)
然后我们的新config将存储替换的值,当然它不会覆盖原始的.yml文件。 我希望你发现这很有用,我真的这样做,因为它正是我所需要的。
我使用百分比%令牌,但您可以将其更改为您想要的任何内容并更改方法以使其与正则表达式一起使用(正则表达式使用了一些令牌,这就是我使用%的原因)
Well, I've been working on a solution because nothing was what I wanted and everything was so complex I wanted to die...
This solutions transforms a %something% string into the value for something.
It works perfectly, this is an example
root_path: /root
script_path: "%root%/scripts"
With this method, script_path will become /root/scripts.
def replace_values(yaml_file):
def _get(dict, list):
return reduce(lambda d, k: d[k], list, dict)
def _replace(obj):
for k, v in obj.iteritems():
if isinstance(v, dict):
_replace(v)
if isinstance(v, str):
match = re.match(r'%(.*)%', v)
if match:
reference = match.group(1).split('.')
replace = _get(yaml_file, reference)
obj[k] = re.sub(r'%.*%', replace, v)
_replace(yaml_file)
return yaml_file
Usage is easy, just load a Yaml file the normal way, and call replace.
with open(config_file.get(options.env), 'r') as ymlfile:
config = yaml.load(ymlfile)
config = replace_values(config)
Then our new config will store the replaced values, it doesn't overwrite the original .yml file of course. I hope you find this useful, I really do because it was exactly what I needed.
I used a percentage % token, but you can change it to whatever you want and change the method to make it work with regex (some tokens are used by regex that's why I used %)
2015-06-18
相关问答
安装一个pyyaml库。它会解析这个文件,变成一个类似json加载后的结构。字典,列表什么的。然后自己找参数。 ssh命令同样要使用一个库。简单的办法是通过一个封装popen这样功能 的pexpect , 我以前用过paramiko。 另外似乎还有一个SSH库,最近流行的。不记得名子了。 也有人用ssh4py 这个库。 yaml这个格式比较人性化,易读,易管理。比json还要简单。比xml少了编码和解析成DOM的麻烦。
看看检查模块 - 这将为您检查各种代码对象属性。 >>> inspect.getargspec(aMethod)
(['arg1', 'arg2'], None, None, None)
其他结果是* args和** kwargs变量的名称以及提供的默认值。 即。 >>> def foo(a,b,c=4, *arglist, **keywords): pass
>>> inspect.getargspec(foo)
(['a', 'b', 'c'], 'arglist', 'keywords',
...
在Load实例中动态获取可变path有许多不同的解决方案,其中包括: 您可以创建一个Load工厂对象,并在load_constructor设置工厂的path ,而不是直接调用工厂。 你可以使load_constructor成为一个类的实例,在该实例上设置path ,并让它的__call__方法完成构造 你可以用后者来做到这一点: import ruamel.yaml as yaml
yaml_str = """\
--- !MyData
name: theName
param: paramete
...
好吧,我一直在研究解决方案,因为没有什么是我想要的,一切都是如此复杂,我想死... 此解决方案将%something% string转换为something值的值。 它很完美,这是一个例子 root_path: /root
script_path: "%root%/scripts"
使用此方法, script_path将成为/root/scripts 。 def replace_values(yaml_file):
def _get(dict, list):
return
...
图书馆作者在BitBucket上发表了一篇关于此的评论(2016年5月9日): 评论保存尚未稳定,例如,如果映射的键和值不在同一行并且键(或键和值)都有注释,我需要做一些事情。 我最初的目标是保留现有的评论,而不是操纵。 通过一些实验,我确定了上面问题中提供的示例代码的以下工作: print('Comment 1: ' + loaded.ca.comment[1][0].value)
print('Comment 2: ' + loaded.ca.items['a'][2].value)
prin
...
正如格雷厄姆在他的评论中暗示的那样,你试图将一个布尔值设置为一个字符串。 您应该可以使用一行更新这两个值,请尝试: oc patch scc restricted --patch='{"allowHostDirVolumePlugin": true, "runAsUser":{"type":"RunAsAny"}}' As Graham has alluded to in his comment, you are trying to set a boolean value as a string.
...
我只想补充说,行为并不是不一致的,就像Luke暗示的那样。 试试以下内容 print Foo.__dict__
{'__doc__': None,
'__module__': '__main__',
'm1': ,
'm2': ,
'm3': }
在这里你可以看到Python无法区分m
...
这里的术语存在分歧。 在Java社区中,他们认为所有东西都是有价值的:基元是按值传递的; 引用是按值传递的。 (如果你不相信这一点,只要在这个网站上搜索Java并通过引用传递。)注意,“对象”不是该语言的值; 只有对象的引用是。 它们使用的区别在于,在Java中,当您传递引用时,调用者作用域中的原始引用变量永远不会被被调用者更改(即指向不同的对象),这应该可以通过参考。 只有引用指向的对象可能会发生变异,但这是无关紧要的。 Python值的工作方式与Java中的引用完全相同。 如果我们使用相同的定
...
我发现用于与基本存储的类一起使用yaml的模式是让加载器使用构造函数,以便创建对象的方式与正常生成时相同。 如果我理解你试图正确做什么,这种结构可能会有用: import inspect
import yaml
from collections import OrderedDict
class Serializable(yaml.YAMLObject):
__metaclass__ = yaml.YAMLObjectMetaclass
@property
def _dic
...
有两种方法可以使用IronPython中的out或ref参数调用方法。 在第一种情况下,呼叫由自动编组处理。 返回值和更改的refs包含在一个元组中,并且(以15.1作为示例double传递)可以使用如下: (returned, referenced) = GetValue(15.1)
更明确的方法是提供准备好的clr-reference: refParam = clr.Reference[System.Double](15.1)
result = GetValue(refParam)
The
...