2016-05-20 1 views
1

J'ai un fichier YAML décrivant mes objets etComment passer un paramètre à un constructeur de classe appelée par yaml.load_all

--- !MyData 
name: theName 
param: parameter 
data_file: \\path\to\my\file.csv 

Mon code est le suivant

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) 

Au moment d'initialisation principal utilise ceci pour charger les données

with open(self.initFile, 'r', newline='') as ymlfile: 
    for item in yaml.load_all(ymlfile): 
     if type(item) is Load: 
       ---- some post init code 

Tout fonctionne bien, mais puisque mon code principal connaît déjà le chemin complet de data_file étant donné qu'il est dans le même répertoire que le yaml, est-il un moyen de donner seulement le nom du fichier_données sans chemin complet afin que je puisse changer l'emplacement sans avoir à modifier le fichier de configuration yaml? Comme le fichier_données est chargé par la classe Parent appelée via la fonction yaml.load_all, je ne sais pas comment donner un paramètre indiquant la valeur du chemin.

Répondre

0

Il y a beaucoup de solutions différentes pour obtenir une variable path dynamique dans l'instance de charge, y compris:

  • Vous pouvez créer un objet usine de charge et mis en path sur l'usine dans l'appel load_constructor l'usine au lieu de Load directement.
  • Vous pouvez faire la load_constructor dans une instance d'une classe, mis path sur cette instance et ont sa méthode __call__ faire la construction

Ce dernier vous pourriez faire avec:

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) 

S'il vous plaît noter que j'ai dû changer le premier argument du constructeur sinon un objet YAML de type MyData n'a pas pu être construit. Aussi param doit être défini si vous l'utilisez comme valeur pour Load.__init__() (comme la clé est bien sûr bien), donc je l'ai cité.

exécution ci-dessus (sous python3) vous donnera:

data file: /my/path/to/csv/file.csv