使用ruamel.yaml转储为字符串的最佳方式不是流

过去,我使用ruamel.yaml的向后兼容部分做了类似some_fancy_printing_loggin_func(yaml.dump(...), ...)的工作,但我想将我的代码转换为使用最新的API这样我就可以利用一些新的格式设置。使用ruamel.yaml转储为字符串的最佳方式不是流

但是,我讨厌我必须指定流到ruamel.yaml.YAML.dump() ......我不希望它直接写入流;我只是希望它将输出返回给调用者。我错过了什么? PS:我知道我可以做类似以下的事情,尽管当然我试图避免它。

f = io.StringIO() 

yml.dump(myobj, f)

f.seek(0)

my_logging_func(f.read())

回答:

我不知道,如果你真的失去了一些东西,如果在所有它可能是,如果你与流工作,你应该 - 最好-继续流工作。这不过是一些ruamel.yaml和PyYAML的许多用户似乎没有意识到,所以他们做的:

print(dump(data)) 

代替

dump(data, sys.stdout) 

前者可能是罚款,在使用非真实数据(PyYAML)文档,但会导致真实数据的不良习惯。

最好的解决方案是使您的my_logging_func()流为导向。这可以例如完成如下:

import sys 

import ruamel.yaml

data = dict(user='rsaw', question=47614862)

class MyLogger:

def write(self, s):

sys.stdout.write(s.decode('utf-8'))

my_logging_func = MyLogger()

yml = ruamel.yaml.YAML()

yml.dump(data, my_logging_func)

这给:

user: rsaw 

question: 47614862

但要注意,MyLogger.write()被多次调用(在这种情况下八次),如果你需要在时间上线工作,你必须做线路缓冲。

尽管您可以包装非流式接口,但这并不总是很方便。在ruamel.yaml<=0.15.34中,您可以滥用transform参数。这个参数需要一个函数,它传递给YAML文档的一个完整的字符串表示(与老API返回一个字符串一样低效,所以要小心),哪个应该返回一个转换后的字符串,然后进行流式处理。如果您将流设置为接收器,则不必关心该函数的返回值:

import sys 

import ruamel.yaml

data = dict(user='rsaw', question=47614862)

def my_logging_func(s):

print(s, end='')

class NullStream:

def write(self, s):

pass

yml = ruamel.yaml.YAML()

yml.dump(data, NullStream(), transform=my_logging_func)

获得相同的输出。

随着ruamel.yaml>0.15.34,假设你提供transform参数,可以提供None作为流:

import sys 

import ruamel.yaml

data = dict(user='rsaw', question=47614862)

def my_logging_func(s):

print(s, end='')

yml = ruamel.yaml.YAML()

yml.dump(data, None, transform=my_logging_func)

而且,你甚至可以滥用更多的事情要做:

import ruamel.yaml 

data = dict(user='rsaw', question=47614862)

yml = ruamel.yaml.YAML()

yml.dump(data, None, transform=print)

(但它会在输出结束时为你提供额外的换行符,就像旧的print(dump(data))一样)。

以上是 使用ruamel.yaml转储为字符串的最佳方式不是流 的全部内容, 来源链接: utcz.com/qa/259337.html

回到顶部