PyYAML - Saving data to .yaml files
up vote
0
down vote
favorite
So I've picked up PyYAML over the past few days but I feel like some of the documentation is vague or I'm misinterpreting it. Here is a function for writing data to a .yaml which can write the values to each element I have in the list:
def writeSave(filename, **kwargs):
with open(filename, 'r') as yamlFile:
yamlDict = yaml.load(yamlFile)
if not yamlDict: yamlDict = {}
with open(filename, 'w') as write:
z = yamlDict.copy()
z.update(kwargs)
yaml.dump(z, write)
Which will then overwrite the values below when called:
saveData:
{mission_state: 7, playername: 'steve'}
Using this function seems simple:
writeSave('../path/savedata.yaml', mission_state=2)
Which will then change the mission_state in the list.
I don't know if I've done this smoothly or if there is a better practice to performing these kind of functions. If there are, it'd be nice to have some kind of pointers.
Is there a way to make this more readable? Maybe more readable vars or more commenting?
python yaml
add a comment |
up vote
0
down vote
favorite
So I've picked up PyYAML over the past few days but I feel like some of the documentation is vague or I'm misinterpreting it. Here is a function for writing data to a .yaml which can write the values to each element I have in the list:
def writeSave(filename, **kwargs):
with open(filename, 'r') as yamlFile:
yamlDict = yaml.load(yamlFile)
if not yamlDict: yamlDict = {}
with open(filename, 'w') as write:
z = yamlDict.copy()
z.update(kwargs)
yaml.dump(z, write)
Which will then overwrite the values below when called:
saveData:
{mission_state: 7, playername: 'steve'}
Using this function seems simple:
writeSave('../path/savedata.yaml', mission_state=2)
Which will then change the mission_state in the list.
I don't know if I've done this smoothly or if there is a better practice to performing these kind of functions. If there are, it'd be nice to have some kind of pointers.
Is there a way to make this more readable? Maybe more readable vars or more commenting?
python yaml
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
So I've picked up PyYAML over the past few days but I feel like some of the documentation is vague or I'm misinterpreting it. Here is a function for writing data to a .yaml which can write the values to each element I have in the list:
def writeSave(filename, **kwargs):
with open(filename, 'r') as yamlFile:
yamlDict = yaml.load(yamlFile)
if not yamlDict: yamlDict = {}
with open(filename, 'w') as write:
z = yamlDict.copy()
z.update(kwargs)
yaml.dump(z, write)
Which will then overwrite the values below when called:
saveData:
{mission_state: 7, playername: 'steve'}
Using this function seems simple:
writeSave('../path/savedata.yaml', mission_state=2)
Which will then change the mission_state in the list.
I don't know if I've done this smoothly or if there is a better practice to performing these kind of functions. If there are, it'd be nice to have some kind of pointers.
Is there a way to make this more readable? Maybe more readable vars or more commenting?
python yaml
So I've picked up PyYAML over the past few days but I feel like some of the documentation is vague or I'm misinterpreting it. Here is a function for writing data to a .yaml which can write the values to each element I have in the list:
def writeSave(filename, **kwargs):
with open(filename, 'r') as yamlFile:
yamlDict = yaml.load(yamlFile)
if not yamlDict: yamlDict = {}
with open(filename, 'w') as write:
z = yamlDict.copy()
z.update(kwargs)
yaml.dump(z, write)
Which will then overwrite the values below when called:
saveData:
{mission_state: 7, playername: 'steve'}
Using this function seems simple:
writeSave('../path/savedata.yaml', mission_state=2)
Which will then change the mission_state in the list.
I don't know if I've done this smoothly or if there is a better practice to performing these kind of functions. If there are, it'd be nice to have some kind of pointers.
Is there a way to make this more readable? Maybe more readable vars or more commenting?
python yaml
python yaml
edited Feb 3 at 3:46
asked Feb 3 at 3:35
iZodiac
10815
10815
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
4
down vote
accepted
First, Python has an official style-guide, PEP8, which you should follow. It recommends using
lower_casefor functions and variables.I would also rename your function, since
write_savedoes not say what this function is doing. I thinkoverwrite_settingorupdate_valueor something similar would be better.You might want to add a check if any keyword arguments are passed to the function. Either raise an exception (a simple
AssertionErrormight be enough), or at least don't waste time reading the file and writing the same content back.While
openopens a file in read-mode by default, here I think it is actually fine to open it once explicitly with'r'and then with'w'.Your
z = yamDict.copy()should be completely unnecessary. Mutating the original dictionary does not do any harm. The updating does not need to be within thewithblock either.Finally, you could use
orfor the check of an empty dictionary.
With all of the above changes, your code would become:
import yaml
def update_value(filename, **kwargs):
assert kwargs
with open(filename, 'r') as f:
yaml_dict = yaml.load(f) or {}
yaml_dict.update(kwargs)
with open(filename, 'w') as f:
yaml.dump(yaml_dict, f)
If you have only one thread, you could skip the reading of the config everytime you want to change a value and instead keep the dictionary in memory (after having it read once at the beginning). You will still want the write to save state, though. For this you might want to have a Config class, derived from dict:
import os
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
def __setitem__(self, key, value):
super(Config, self).__setitem__(key, value)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def __delitem__(self, key):
super(Config, self).__delitem__(key)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def update(self, kwargs):
super(Config, self).update(kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
You might want to define a decorator to add the dumping part to the methods:
import functools
def dumps(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
ret = func(self, *args, **kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
return ret
return wrapper
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
__setitem__ = dumps(dict.__setitem__)
__delitem__ = dumps(dict.__delitem__)
update = dumps(dict.update)
You can use this class like a dict, but every change to the dictionary is also dumped to the yaml file. The file is only read once (when the config is initialized), so changes to the file will only be visible when the script is re-started.
cfg = Config("test.yaml")
print(cfg)
cfg['a'] = 3
print(cfg)
cfg.update({"b": 4})
cfg.update(c=5)
del cfg['a']
print(cfg)
1
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
First, Python has an official style-guide, PEP8, which you should follow. It recommends using
lower_casefor functions and variables.I would also rename your function, since
write_savedoes not say what this function is doing. I thinkoverwrite_settingorupdate_valueor something similar would be better.You might want to add a check if any keyword arguments are passed to the function. Either raise an exception (a simple
AssertionErrormight be enough), or at least don't waste time reading the file and writing the same content back.While
openopens a file in read-mode by default, here I think it is actually fine to open it once explicitly with'r'and then with'w'.Your
z = yamDict.copy()should be completely unnecessary. Mutating the original dictionary does not do any harm. The updating does not need to be within thewithblock either.Finally, you could use
orfor the check of an empty dictionary.
With all of the above changes, your code would become:
import yaml
def update_value(filename, **kwargs):
assert kwargs
with open(filename, 'r') as f:
yaml_dict = yaml.load(f) or {}
yaml_dict.update(kwargs)
with open(filename, 'w') as f:
yaml.dump(yaml_dict, f)
If you have only one thread, you could skip the reading of the config everytime you want to change a value and instead keep the dictionary in memory (after having it read once at the beginning). You will still want the write to save state, though. For this you might want to have a Config class, derived from dict:
import os
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
def __setitem__(self, key, value):
super(Config, self).__setitem__(key, value)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def __delitem__(self, key):
super(Config, self).__delitem__(key)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def update(self, kwargs):
super(Config, self).update(kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
You might want to define a decorator to add the dumping part to the methods:
import functools
def dumps(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
ret = func(self, *args, **kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
return ret
return wrapper
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
__setitem__ = dumps(dict.__setitem__)
__delitem__ = dumps(dict.__delitem__)
update = dumps(dict.update)
You can use this class like a dict, but every change to the dictionary is also dumped to the yaml file. The file is only read once (when the config is initialized), so changes to the file will only be visible when the script is re-started.
cfg = Config("test.yaml")
print(cfg)
cfg['a'] = 3
print(cfg)
cfg.update({"b": 4})
cfg.update(c=5)
del cfg['a']
print(cfg)
1
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
add a comment |
up vote
4
down vote
accepted
First, Python has an official style-guide, PEP8, which you should follow. It recommends using
lower_casefor functions and variables.I would also rename your function, since
write_savedoes not say what this function is doing. I thinkoverwrite_settingorupdate_valueor something similar would be better.You might want to add a check if any keyword arguments are passed to the function. Either raise an exception (a simple
AssertionErrormight be enough), or at least don't waste time reading the file and writing the same content back.While
openopens a file in read-mode by default, here I think it is actually fine to open it once explicitly with'r'and then with'w'.Your
z = yamDict.copy()should be completely unnecessary. Mutating the original dictionary does not do any harm. The updating does not need to be within thewithblock either.Finally, you could use
orfor the check of an empty dictionary.
With all of the above changes, your code would become:
import yaml
def update_value(filename, **kwargs):
assert kwargs
with open(filename, 'r') as f:
yaml_dict = yaml.load(f) or {}
yaml_dict.update(kwargs)
with open(filename, 'w') as f:
yaml.dump(yaml_dict, f)
If you have only one thread, you could skip the reading of the config everytime you want to change a value and instead keep the dictionary in memory (after having it read once at the beginning). You will still want the write to save state, though. For this you might want to have a Config class, derived from dict:
import os
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
def __setitem__(self, key, value):
super(Config, self).__setitem__(key, value)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def __delitem__(self, key):
super(Config, self).__delitem__(key)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def update(self, kwargs):
super(Config, self).update(kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
You might want to define a decorator to add the dumping part to the methods:
import functools
def dumps(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
ret = func(self, *args, **kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
return ret
return wrapper
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
__setitem__ = dumps(dict.__setitem__)
__delitem__ = dumps(dict.__delitem__)
update = dumps(dict.update)
You can use this class like a dict, but every change to the dictionary is also dumped to the yaml file. The file is only read once (when the config is initialized), so changes to the file will only be visible when the script is re-started.
cfg = Config("test.yaml")
print(cfg)
cfg['a'] = 3
print(cfg)
cfg.update({"b": 4})
cfg.update(c=5)
del cfg['a']
print(cfg)
1
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
add a comment |
up vote
4
down vote
accepted
up vote
4
down vote
accepted
First, Python has an official style-guide, PEP8, which you should follow. It recommends using
lower_casefor functions and variables.I would also rename your function, since
write_savedoes not say what this function is doing. I thinkoverwrite_settingorupdate_valueor something similar would be better.You might want to add a check if any keyword arguments are passed to the function. Either raise an exception (a simple
AssertionErrormight be enough), or at least don't waste time reading the file and writing the same content back.While
openopens a file in read-mode by default, here I think it is actually fine to open it once explicitly with'r'and then with'w'.Your
z = yamDict.copy()should be completely unnecessary. Mutating the original dictionary does not do any harm. The updating does not need to be within thewithblock either.Finally, you could use
orfor the check of an empty dictionary.
With all of the above changes, your code would become:
import yaml
def update_value(filename, **kwargs):
assert kwargs
with open(filename, 'r') as f:
yaml_dict = yaml.load(f) or {}
yaml_dict.update(kwargs)
with open(filename, 'w') as f:
yaml.dump(yaml_dict, f)
If you have only one thread, you could skip the reading of the config everytime you want to change a value and instead keep the dictionary in memory (after having it read once at the beginning). You will still want the write to save state, though. For this you might want to have a Config class, derived from dict:
import os
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
def __setitem__(self, key, value):
super(Config, self).__setitem__(key, value)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def __delitem__(self, key):
super(Config, self).__delitem__(key)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def update(self, kwargs):
super(Config, self).update(kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
You might want to define a decorator to add the dumping part to the methods:
import functools
def dumps(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
ret = func(self, *args, **kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
return ret
return wrapper
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
__setitem__ = dumps(dict.__setitem__)
__delitem__ = dumps(dict.__delitem__)
update = dumps(dict.update)
You can use this class like a dict, but every change to the dictionary is also dumped to the yaml file. The file is only read once (when the config is initialized), so changes to the file will only be visible when the script is re-started.
cfg = Config("test.yaml")
print(cfg)
cfg['a'] = 3
print(cfg)
cfg.update({"b": 4})
cfg.update(c=5)
del cfg['a']
print(cfg)
First, Python has an official style-guide, PEP8, which you should follow. It recommends using
lower_casefor functions and variables.I would also rename your function, since
write_savedoes not say what this function is doing. I thinkoverwrite_settingorupdate_valueor something similar would be better.You might want to add a check if any keyword arguments are passed to the function. Either raise an exception (a simple
AssertionErrormight be enough), or at least don't waste time reading the file and writing the same content back.While
openopens a file in read-mode by default, here I think it is actually fine to open it once explicitly with'r'and then with'w'.Your
z = yamDict.copy()should be completely unnecessary. Mutating the original dictionary does not do any harm. The updating does not need to be within thewithblock either.Finally, you could use
orfor the check of an empty dictionary.
With all of the above changes, your code would become:
import yaml
def update_value(filename, **kwargs):
assert kwargs
with open(filename, 'r') as f:
yaml_dict = yaml.load(f) or {}
yaml_dict.update(kwargs)
with open(filename, 'w') as f:
yaml.dump(yaml_dict, f)
If you have only one thread, you could skip the reading of the config everytime you want to change a value and instead keep the dictionary in memory (after having it read once at the beginning). You will still want the write to save state, though. For this you might want to have a Config class, derived from dict:
import os
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
def __setitem__(self, key, value):
super(Config, self).__setitem__(key, value)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def __delitem__(self, key):
super(Config, self).__delitem__(key)
with open(self.filename, "w") as f:
yaml.dump(self, f)
def update(self, kwargs):
super(Config, self).update(kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
You might want to define a decorator to add the dumping part to the methods:
import functools
def dumps(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
ret = func(self, *args, **kwargs)
with open(self.filename, "w") as f:
yaml.dump(self, f)
return ret
return wrapper
class Config(dict):
def __init__(self, filename):
self.filename = filename
if os.path.isfile(filename):
with open(filename) as f:
# use super here to avoid unnecessary write
super(Config, self).update(yaml.load(f) or {})
__setitem__ = dumps(dict.__setitem__)
__delitem__ = dumps(dict.__delitem__)
update = dumps(dict.update)
You can use this class like a dict, but every change to the dictionary is also dumped to the yaml file. The file is only read once (when the config is initialized), so changes to the file will only be visible when the script is re-started.
cfg = Config("test.yaml")
print(cfg)
cfg['a'] = 3
print(cfg)
cfg.update({"b": 4})
cfg.update(c=5)
del cfg['a']
print(cfg)
edited 8 hours ago
answered Feb 3 at 12:19
Graipher
23k53384
23k53384
1
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
add a comment |
1
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
1
1
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
Amazing! Really insightful and well explained. I specifically enjoyed the derived dict class since that can really simplify things for me.
– iZodiac
Feb 3 at 14:20
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186653%2fpyyaml-saving-data-to-yaml-files%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown