使用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