Search code examples
pythonyamlpyyaml

How can I tell Pyyaml to convert PosixPath to str in yaml.dump?


I understand that YAML allows you to represent arbitrary data using tags. I would like to convert a PosixPath to a str instead of representing it as a !!pathlib.PosixPath. How can I tell pyyaml to convert PosixPath to str every time it encounters the type?


Solution

  • To represent pathlib instances as generic strings, use the tag:yaml.org,2002:str scalar tag (see the spec section 10.1.1.3).

    To add this representer for default dumpers:

    import pathlib
    import yaml.dumper
    
    data = {"me": pathlib.Path("/home/xaviersjs")}
    
    def path_representer(dumper, obj):
        return dumper.represent_scalar("tag:yaml.org,2002:str", str(obj))
    
    for dumper_name in yaml.dumper.__all__:
        Dumper = getattr(yaml.dumper, dumper_name)
        yaml.add_representer(
            type(pathlib.Path()),
            path_representer,
            Dumper,
        )
    
    print(yaml.dump(data))
    print(yaml.safe_dump(data))
    

    Note that this globally modifies the default behavior of PyYAML. That might be acceptable if you're doing this in an application, but it is unacceptable for a library to modify global mutable state.

    If you're a library, make your own patched dumper type and use it explicitly, don't modify the global mutable state of PyYAML itself:

    import pathlib
    import yaml.dumper
    
    data = {"me": pathlib.Path("/home/xaviersjs")}
    
    def path_representer(dumper, obj):
        return dumper.represent_scalar("tag:yaml.org,2002:str", str(obj))
    
    class MyDumper(yaml.dumper.SafeDumper):
        pass
    
    yaml.add_representer(
        type(pathlib.Path()),
        path_representer,
        MyDumper,
    )
    
    print("patched:", yaml.dump(data, Dumper=MyDumper))
    print("default:", yaml.dump(data))