如何将参数传递给 yaml.load_all 调用的 class 构造函数
How to pass a parameter to a class constructor called by yaml.load_all
我有一个描述我的对象的 YAML 文件和
--- !MyData
name: theName
param: parameter
data_file: \path\to\my\file.csv
我的代码如下
class Load(Parent):
def __init__(self, name="",
param = param,
useDataFile=False,
data_file = "none",
**kwargs):
super().__init__(name=name,
data_file = data_file)
def load_constructor(loader, node):
values = loader.construct_mapping(node, deep=True)
return Load(**values)
yaml.add_constructor(u'!Load', load_constructor)
在初始化时,主要使用它来加载数据
with open(self.initFile, 'r', newline='') as ymlfile:
for item in yaml.load_all(ymlfile):
if type(item) is Load:
---- some post init code
一切正常,但由于我的主代码已经知道 data_file 的完整路径,因为它与 yaml 位于同一目录中,
有没有办法只给出没有完整路径的 data_file 的名称,这样我就可以在不编辑 yaml 配置文件的情况下更改位置?由于 data_file 是由通过 yaml.load_all 函数调用的父 class 加载的,我不知道如何给一个参数告诉路径值。
在Load实例中动态获取一个变量path
有很多不同的解决方案,包括:
- 您可以创建一个 Load 工厂对象,并在
load_constructor
调用工厂而不是直接 Load
中设置 path
on factory。
- 您可以将 load_constructor 变成 class 的实例,在该实例上设置
path
并让其 __call__
方法执行构造
后者你可以用:
import ruamel.yaml as yaml
yaml_str = """\
--- !MyData
name: theName
param: parameter
data_file: file.csv
"""
class Parent:
def __init__(self, name, data_file, path=None):
self._name = name
self._data_file = (path + data_file) if path is not None else data_file
class Load(Parent):
def __init__(self, name="",
param = "param",
useDataFile=False,
data_file = "none",
path=None,
**kwargs):
super().__init__(name=name,
data_file = data_file, path=path)
class LoadConstructor:
def __init__(self, path=None):
self._path = None
def set_path(self, path):
self._path = path
def __call__(self, loader, node):
values = loader.construct_mapping(node, deep=True)
values['path'] = self._path
return Load(**values)
load_constructor = LoadConstructor()
yaml.add_constructor(u'!MyData', load_constructor)
# using the above:
# set the default path
load_constructor.set_path('/my/path/to/csv/')
# parse YAML documents
for item in yaml.load_all(yaml_str):
if type(item) is Load:
print('data file:', item._data_file)
请注意,我必须更改构造函数的第一个参数,否则无法构造 MyData
类型的 YAML 对象。如果将 param
用作 Load.__init__()
的值(因为 key 当然可以),也需要定义 param
,所以我引用了它。
运行 以上(在 Python3 下)会给你:
data file: /my/path/to/csv/file.csv
我有一个描述我的对象的 YAML 文件和
--- !MyData
name: theName
param: parameter
data_file: \path\to\my\file.csv
我的代码如下
class Load(Parent):
def __init__(self, name="",
param = param,
useDataFile=False,
data_file = "none",
**kwargs):
super().__init__(name=name,
data_file = data_file)
def load_constructor(loader, node):
values = loader.construct_mapping(node, deep=True)
return Load(**values)
yaml.add_constructor(u'!Load', load_constructor)
在初始化时,主要使用它来加载数据
with open(self.initFile, 'r', newline='') as ymlfile:
for item in yaml.load_all(ymlfile):
if type(item) is Load:
---- some post init code
一切正常,但由于我的主代码已经知道 data_file 的完整路径,因为它与 yaml 位于同一目录中, 有没有办法只给出没有完整路径的 data_file 的名称,这样我就可以在不编辑 yaml 配置文件的情况下更改位置?由于 data_file 是由通过 yaml.load_all 函数调用的父 class 加载的,我不知道如何给一个参数告诉路径值。
在Load实例中动态获取一个变量path
有很多不同的解决方案,包括:
- 您可以创建一个 Load 工厂对象,并在
load_constructor
调用工厂而不是直接Load
中设置path
on factory。 - 您可以将 load_constructor 变成 class 的实例,在该实例上设置
path
并让其__call__
方法执行构造
后者你可以用:
import ruamel.yaml as yaml
yaml_str = """\
--- !MyData
name: theName
param: parameter
data_file: file.csv
"""
class Parent:
def __init__(self, name, data_file, path=None):
self._name = name
self._data_file = (path + data_file) if path is not None else data_file
class Load(Parent):
def __init__(self, name="",
param = "param",
useDataFile=False,
data_file = "none",
path=None,
**kwargs):
super().__init__(name=name,
data_file = data_file, path=path)
class LoadConstructor:
def __init__(self, path=None):
self._path = None
def set_path(self, path):
self._path = path
def __call__(self, loader, node):
values = loader.construct_mapping(node, deep=True)
values['path'] = self._path
return Load(**values)
load_constructor = LoadConstructor()
yaml.add_constructor(u'!MyData', load_constructor)
# using the above:
# set the default path
load_constructor.set_path('/my/path/to/csv/')
# parse YAML documents
for item in yaml.load_all(yaml_str):
if type(item) is Load:
print('data file:', item._data_file)
请注意,我必须更改构造函数的第一个参数,否则无法构造 MyData
类型的 YAML 对象。如果将 param
用作 Load.__init__()
的值(因为 key 当然可以),也需要定义 param
,所以我引用了它。
运行 以上(在 Python3 下)会给你:
data file: /my/path/to/csv/file.csv