-1

Instead of having to declare the variables and their values in the script, I would like to have them declared externally in a separate YAML file called settings.yml:

setting1: cat
setting2: dog

Is there a way to use the variables' names and values directly as if I declare them internally? E.g. running print(setting1, setting2) returns cat dog. So far I can only read it:

import yaml

with open("settings.yml", "r") as stream:
    try:
        data = yaml.safe_load(stream)
        for key, value in data.items():
            print(f"{key}: {value}")
    except yaml.YAMLError as exc:
        print(exc)

print(setting1, setting2)

The print(setting1, setting2) doesn't work. I take a look at the PyYAML documentation but am unable to find it.

Ooker
  • 1,969
  • 4
  • 28
  • 58
  • Why _would_ `print(setting1, setting2)` work? You have a dictionary that (presumably) contains those values but haven't actually assigned them to variables more specific than `data`. Maybe see https://stackoverflow.com/q/1373164/3001761, but **TL;DR** just _use the dictionary_. – jonrsharpe May 28 '23 at 13:48
  • 1
    Its all well and good storing data in a `yaml` file, but what if later on you edit the data file and accidentally/on purpose change the variable names? Your `python` program would break. Then you are in the situation of having to manually keep two files in sync. – quamrana May 28 '23 at 13:57
  • @quamrana is there a way to tell the IDE to rename them automatically? I use VS Code – Ooker May 28 '23 at 13:58
  • @jonrsharpe you mean I should have a dictionary named `settings`, and refer to individual ones as `setting['settings1']`, `setting['setting2']`? That's so mouthful – Ooker May 29 '23 at 17:25

2 Answers2

1

I am not sure if what you want to do is a good idea, but it can be achieved by assigning to globals(). Assuming the document containing your YAML file contains a root level mapping:

from pathlib import Path
import ruamel.yaml

file_in = Path('settings.yaml')

    
yaml = ruamel.yaml.YAML()
data = yaml.load(file_in)
for k, v in data.items():
    globals()[k] = v

print(setting1, setting2)

which gives:

cat dog

The officially recommended extension for files containing YAML documents has been .yaml, since at least September 2006

Anthon
  • 69,918
  • 32
  • 186
  • 246
  • Cool trick. I have some questions. Why do you think this is not a good idea? And why do you use the ruamel package instead of yaml? – Ooker May 31 '23 at 07:42
  • Global variables are something usually frowned upon. If you leave things in `data`, you can much moreeasily just iterate over the keys of the mapping, once they are in globals there is all kind of other stuff. `yaml` is provided by PyYAML, which can handle a subset of YAML 1.1. which was replaced by YAML 1.2 in 2009. `ruamel.yaml`, apart from me be the author, support YAML 1.2, and has a few other advantages. – Anthon May 31 '23 at 13:11
  • interesting. I suppose that you have a detailed page explaining the reason why you want to make a different package rather than contribute to PyYAML, right? Can I see it? – Ooker May 31 '23 at 16:04
  • There is some of that in the documentation. Being able to preserve comments on round trip (load-modify-dump) was the primary reason as well YAML 1.2 support, support for complex keys in mappings. PyYAML had not been updated for several years when I forked back in 2014, and not much has happened with it since. – Anthon May 31 '23 at 21:06
  • so is it because the author didn't accept any pull request or reply to any issue that you forked it? – Ooker Jun 01 '23 at 13:52
  • 1
    PyYAML used to have two directories with sources, one with Python2 and one with Python3, the same files and only differing in about 2%. So my initial pull request was to merge these to be 2 and 3 compatible, after which actual changes would have been easier (and they were because I made the first comment preserving changes on the merged source, not wanting to have to do them twice), after several months there was no reply, also not on direct emails to the author, asking if the project was dead (or he just busy). I couldn't wait for the PyYAML release cycle of 2-3 years. – Anthon Jun 01 '23 at 20:09
0

Stupid me. Instead of using YAML I just need to make it a module, e.g. settings.py. Then from settings import *. However if you have a canonical answer for YAML, I'll happy to accept it.

Ooker
  • 1,969
  • 4
  • 28
  • 58
  • This is the way to go. Now most IDEs will recognise all your modules and be able to perform a rename of variables when you need it. – quamrana May 28 '23 at 14:23