如何防止YAML转储长行而不换行

问题描述 投票:0回答:2

在转储/序列化输入中具有长行的数据时,pyyaml 添加额外的缩进和新行 - 这很烦人,我们如何避免在两行/多行中进行这种转换?

例如

In [1]: x = "-c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/ --optnion12 --verbose"
In [2]: import yaml
In [3]: print (yaml.dump([dict(ATTRIBUTES=[dict(CONFIG=x)])], default_flow_style=False))

错了

- ATTRIBUTES:
  - CONFIG: -c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/
      --optnion12 --verbose

应该是这样的

- ATTRIBUTES:
  - CONFIG: -c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/ --optnion12 --verbose
python yaml line-breaks dump long-lines
2个回答
76
投票

感谢 @MathieuMarques 建议查看 @ dump 选项和提供的链接,YAML 文档还不够好,无法找到它。

无论如何,解决方案是为

width
函数指定
dump
参数。

yaml.dump(data, width=1000)

@RandomCoder建议使用

yaml.dump(data, width=float("inf"))
作为永久解决方案的更好方法。


0
投票

我在 Ansible 插件中尝试了

sys.maxsize
float("inf")
,当我遇到错误时非常困惑。我发现使用
CDumper
时,可以使用
-1
的值来实现无限宽度,并且不能使用大数字。

import yaml
from yaml import Dumper, CDumper
x = [dict(ATTRIBUTES=[dict(CONFIG="-c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/ --optnion12 --verbose")])]
print("python dumper -1")
print(yaml.dump(x, width=-1, Dumper=Dumper))
print("python dumper inf")
print(yaml.dump(x, width=float("inf"), Dumper=Dumper))
print("C dumper -1")
print(yaml.dump(x, width=-1, Dumper=CDumper))
print("C dumper inf")
print(yaml.dump(x, width=float("inf"), Dumper=CDumper))
python dumper -1
- ATTRIBUTES:
  - CONFIG: -c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/
      --optnion12 --verbose

python dumper inf
- ATTRIBUTES:
  - CONFIG: -c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/ --optnion12 --verbose

C dumper -1
- ATTRIBUTES:
  - CONFIG: -c /home/user/test/test2/test23/tet/2s/test1/stest/longdirectory1/directory2/ --optnion12 --verbose

C dumper inf
Traceback (most recent call last):
  File "/private/tmp/test-yaml.py", line 12, in <module>
    print(yaml.dump([dict(ATTRIBUTES=[dict(CONFIG=x)])], width=float("inf"), Dumper=CDumper))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/simon/.local/lib/python3.12/site-packages/yaml/__init__.py", line 253, in dump
    return dump_all([data], stream, Dumper=Dumper, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/simon/.local/lib/python3.12/site-packages/yaml/__init__.py", line 232, in dump_all
    dumper = Dumper(stream, default_style=default_style,
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/simon/.local/lib/python3.12/site-packages/yaml/cyaml.py", line 93, in __init__
    CEmitter.__init__(self, stream, canonical=canonical,
  File "yaml/_yaml.pyx", line 921, in yaml._yaml.CEmitter.__init__
OverflowError: cannot convert float infinity to integer

CDumper源代码:

https://github.com/yaml/pyyaml/blob/69c141adcf805c5ebdc9ba519927642ee5c7f639/lib/yaml/cyaml.py#L85-L94

class CDumper(...):
    def __init__(..., width=None, ...):
        CEmitter.__init__(..., width=width, ...)

https://github.com/yaml/pyyaml/blob/69c141adcf805c5ebdc9ba519927642ee5c7f639/yaml/_yaml.pyx#L920-L921

cdef class CEmitter:
    ...
    def __init__(..., width=None, ...)
        ...
        if width is not None:
            yaml_emitter_set_width(..., width)

https://github.com/yaml/libyaml/blob/840b65c40675e2d06bf40405ad3f12dec7f35923/src/api.c#L548-L553

yaml_emitter_set_width(..., int width)
{
    assert(emitter);    /* Non-NULL emitter object expected. */

    emitter->best_width = (width >= 0) ? width : -1;
}

https://github.com/yaml/libyaml/blob/840b65c40675e2d06bf40405ad3f12dec7f35923/src/emitter.c#L518-L520

        if (emitter->best_width < 0) {
            emitter->best_width = INT_MAX;
        }

转储器源代码:

https://github.com/yaml/pyyaml/blob/69c141adcf805c5ebdc9ba519927642ee5c7f639/lib/yaml/dumper.py#L45-L55

class Dumper(...):
    def __init__(..., width=None, ...):
        Emitter.__init__(..., width=width, ...)

https://github.com/yaml/pyyaml/blob/69c141adcf805c5ebdc9ba519927642ee5c7f639/lib/yaml/emitter.py#L88-L90

class Emitter:
    def __init__(..., width=None, ...):
        ...
        self.best_width = 80
        if width and width > self.best_indent*2:
            self.best_width = width
© www.soinside.com 2019 - 2024. All rights reserved.