У меня есть это:
user_dir: /home/user
user_pics: /home/user/pics
Как я могу использовать user_dir
для user_pics? Если бы мне пришлось указать другие подобные свойства, это было бы не очень СУХОЕ.
У меня есть это:
user_dir: /home/user
user_pics: /home/user/pics
Как я могу использовать user_dir
для user_pics? Если бы мне пришлось указать другие подобные свойства, это было бы не очень СУХОЕ.
Вы можете использовать повторяющийся узел, например:
user_dir: &user_home /home/user
user_pics: *user_home
Я не думаю, что вы можете объединить, поэтому это не сработает:
user_dir: &user_home /home/user
user_pics: *user_home/pics
Это удивительно, поскольку цель привязок и ссылок YAML состоит в том, чтобы исключить дублирование файлов данных YAML, что не существует встроенного способа объединения строк с использованием ссылок. Ваш вариант использования создания имени пути из частей является хорошим примером - таких применений должно быть много.
К счастью, есть простой способ добавить конкатенацию строк в YAML с помощью настраиваемых тегов в Python.
import yaml
## define custom tag handler
def join(loader, node):
seq = loader.construct_sequence(node)
return ''.join([str(i) for i in seq])
## register the tag handler
yaml.add_constructor('!join', join)
## using your sample data
yaml.load("""
user_dir: &DIR /home/user
user_pics: !join [*DIR, /pics]
""")
Что приводит к:
{'user_dir': '/home/user', 'user_pics': '/home/user/pics'}
Вы можете добавить в массив больше элементов, например " "
или "-"
, если строки должны быть разделены.
yaml
. Он просто использует свои общедоступные API-интерфейсы, чтобы расширить его так, как это разрешено спецификацией YAML.
- person Ken Williams; 11.03.2020
Если вы используете python с PyYaml, соединение строк возможно в файле YAML. К сожалению, это всего лишь решение на Python, а не универсальное:
с os.path.join
:
user_dir: &home /home/user
user_pics: !!python/object/apply:os.path.join [*home, pics]
с string.join
(для полноты картины - этот метод может использоваться для нескольких форм соединения строк:
user_dir: &home /home/user
user_pics: !!python/object/apply:string.join [[*home, pics], /]
yaml.safe_load()
, чтобы избежать проблем с безопасностью. В этом случае ваш код не будет работать.
- person Chris Johnson; 30.08.2015
cannot find module 'str' (No module named 'str')
- person Jeremy Leipzig; 16.06.2016
Я бы использовал массив, а затем присоединил бы строку вместе с текущим символом разделителя ОС
нравится:
default: &default_path "you should not use paths in config"
pictures:
- *default_path
- pics
Мне кажется, что сам YAML не определяет способ сделать это.
Хорошая новость заключается в том, что потребитель YAML может понимать переменные.
Что будет использовать ваш YAML?
string.join()
не будет работать в Python3, но вы можете определить !join
следующим образом:
import functools
import yaml
class StringConcatinator(yaml.YAMLObject):
yaml_loader = yaml.SafeLoader
yaml_tag = '!join'
@classmethod
def from_yaml(cls, loader, node):
return functools.reduce(lambda a, b: a.value + b.value, node.value)
c=yaml.safe_load('''
user_dir: &user_dir /home/user
user_pics: !join [*user_dir, /pics]''')
print(c)
По состоянию на август 2019 г.:
Чтобы решение Криса работало, вам действительно нужно добавить Loader=yaml.Loader
в yaml.load()
. В конечном итоге код будет выглядеть так:
import yaml
## define custom tag handler
def join(loader, node):
seq = loader.construct_sequence(node)
return ''.join([str(i) for i in seq])
## register the tag handler
yaml.add_constructor('!join', join)
## using your sample data
yaml.load("""
user_dir: &DIR /home/user
user_pics: !join [*DIR, /pics]
""", Loader=yaml.Loader)
См. эту проблему GitHub для дальнейшего обсуждения.