Как заставить PyYAML загружать строки как объекты unicode?
-
04-10-2019 - |
Вопрос
Пакет PyYAML загружает немаркированные строки либо как объекты unicode, либо как str, в зависимости от их содержимого.
Я хотел бы использовать объекты Unicode во всей своей программе (и, к сожалению, пока не могу переключиться на Python 3).
Есть ли простой способ заставить PyYAML всегда загружать объекты unicode в виде строк?Я не хочу загромождать свой YAML !!python/unicode
Теги.
# Encoding: UTF-8
import yaml
menu= u"""---
- spam
- eggs
- bacon
- crème brûlée
- spam
"""
print yaml.load(menu)
Выходной сигнал: ['spam', 'eggs', 'bacon', u'cr\xe8me br\xfbl\xe9e', 'spam']
Я бы хотел: [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']
Решение
Вот версия, которая переопределяет обработку строк PyYAML, всегда выводя unicode
.На самом деле, это, вероятно, идентичный результат другого ответа, который я опубликовал, за исключением более короткого (т.е.вам все равно нужно убедиться, что строки в пользовательских классах преобразованы в unicode
или прошел unicode
строите сами, если вы используете пользовательские обработчики):
# -*- coding: utf-8 -*-
import yaml
from yaml import Loader, SafeLoader
def construct_yaml_str(self, node):
# Override the default string handling function
# to always return unicode objects
return self.construct_scalar(node)
Loader.add_constructor(u'tag:yaml.org,2002:str', construct_yaml_str)
SafeLoader.add_constructor(u'tag:yaml.org,2002:str', construct_yaml_str)
print yaml.load(u"""---
- spam
- eggs
- bacon
- crème brûlée
- spam
""")
(Вышесказанное дает [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']
)
Я не тестировал это на LibYAML
(анализатор на основе c), поскольку я не смог его скомпилировать, поэтому я оставлю другой ответ таким, каким он был.
Другие советы
Вот функция, которую вы могли бы использовать для замены str
с unicode
типы из декодированного вывода PyYAML
:
def make_str_unicode(obj):
t = type(obj)
if t in (list, tuple):
if t == tuple:
# Convert to a list if a tuple to
# allow assigning to when copying
is_tuple = True
obj = list(obj)
else:
# Otherwise just do a quick slice copy
obj = obj[:]
is_tuple = False
# Copy each item recursively
for x in xrange(len(obj)):
obj[x] = make_str_unicode(obj[x])
if is_tuple:
# Convert back into a tuple again
obj = tuple(obj)
elif t == dict:
for k in obj:
if type(k) == str:
# Make dict keys unicode
k = unicode(k)
obj[k] = make_str_unicode(obj[k])
elif t == str:
# Convert strings to unicode objects
obj = unicode(obj)
return obj
print make_str_unicode({'blah': ['the', 'quick', u'brown', 124]})