18

I am seeing that PyYaml, truncates zero's while loading from yaml file, if one uses: yaml.safe_load(stream).

It can be fixed, if one uses yaml.load(stream, Loader=yaml.BaseLoader), but is that advisable?

It works with yaml.load and zeros are not truncated.

I want to understand that would it be safe to switch to yaml.load instead of yaml.safe_load?

Example:

Test yaml content:

$cat test.yml
number: 5.10

Code:

$python -c 'import yaml, sys; content = yaml.safe_load(sys.stdin); 
print(content) ' < test.yml
{'number': 5.1}

<< It truncates the 0 at the end. But that is due to floating point value >>

whereas what I want is the exact number as is.

$python -c 'import yaml, sys; content = yaml.load(sys.stdin, 
Loader=yaml.BaseLoader); print(content) ' < test.yml
{u'number': u'5.10'}

Is that the correct approach to change it to yaml.load ?

iDev
  • 2,163
  • 10
  • 39
  • 64
  • 1
    Could you give an example of what you mean by truncating zeros? – David Z Sep 16 '20 at 00:46
  • I don't know if that helps very much. All you've added are some numbers, but that doesn't clarify anything. How are the numbers being represented in a YAML file? What code exactly do you use to load the file, and what code do you use to find that zeros are being truncated? What is its output? Probably a lot of what's listed in https://stackoverflow.com/help/minimal-reproducible-example would be useful to add here. – David Z Sep 16 '20 at 01:00
  • 3
    That's not really a complete example, but let me try to clarify. Is your complaint that `yaml.safe_load("5.10")` returns `5.1`? If so, your problem is not that it "truncates zeroes," but that it parses it as a float. The exact solution will likely depend on what you're trying to do, so could you give more information about your use case? – Brian McCutchon Sep 16 '20 at 01:03
  • Using `yaml.BaseLoader` is not recommended as it has known security vulnerabilities. Trailing zero is meaningless if we're talking about a value after the decimal point and you can always get back the (again, meaningless) precision when printing the value, e.g. `print("{:.2f}".format(number))` – Jean Spector Mar 03 '22 at 14:44

1 Answers1

22

yaml.safe_load(sys.stdin) just does yaml.load(sys.stdin, Loader=yaml.SafeLoader).

The facilities to execute arbitrary Python code (which makes loading unsafe) are implemented in yaml.Loader which is used by default. yaml.BaseLoader does not contain them. Therefore, if you use yaml.BaseLoader, loading will not execute arbitrary Python code (that is, unless you yourself register custom constructors with yaml.BaseLoader).

flyx
  • 35,506
  • 7
  • 89
  • 126
  • Thanks @flyx, I am still unable to figure out how do I preserve the trailing zeros in a floating number when I load the yaml file. Any pointers for that? – iDev Sep 17 '20 at 01:17
  • You can do one of two things: Either load the value as [IEEE 754 floating point number](https://en.wikipedia.org/wiki/IEEE_754) (standard representation of floats), this will lose the zero because it does not change the value. Or load the value as string, which you are doing when using `BaseLoader`. Then it is a string and you can't do arithmetic with it, but it preserves its representation. You have shown code for doing each thing so you know how to do it, what's still unclear? – flyx Sep 17 '20 at 08:12