Wie PyYAML zu laden Strings als Unicode-Objekte zu zwingen?
-
04-10-2019 - |
Frage
Die PyYAML Paket lädt unmarkierte Strings als entweder Unicode oder str Objekte, je nach ihrem Inhalt.
Ich möchte Unicode-Objekte in meinem Programm verwenden (und leider nicht wechseln zu Python 3 nur noch) nicht.
Gibt es eine einfache Möglichkeit, PyYAML immer Strings Last Unicode-Objekte zu zwingen? Ich will nicht meine YAML mit !!python/unicode
Tags Krempel.
# Encoding: UTF-8
import yaml
menu= u"""---
- spam
- eggs
- bacon
- crème brûlée
- spam
"""
print yaml.load(menu)
Ausgabe: ['spam', 'eggs', 'bacon', u'cr\xe8me br\xfbl\xe9e', 'spam']
Ich möchte: [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']
Lösung
Hier ist eine Version, die die PyYAML Handhabung von Strings, indem sie immer die Ausgabe unicode
außer Kraft setzt. In Wirklichkeit ist dies wahrscheinlich das gleiche Ergebnis der andere Antwort habe ich geschrieben, außer kürzer (das heißt Sie noch sicherstellen müssen, dass die Strings in benutzerdefinierten Klassen zu unicode
umgewandelt werden oder weitergegeben unicode
Strings selbst, wenn Sie benutzerdefinierte Handler verwenden):
# -*- 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
""")
(Obige gibt [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']
)
Ich habe nicht getestet es auf LibYAML
(die c-basierten Parsern), wie ich es allerdings nicht kompilieren konnte, so dass ich die andere Antwort verlassen würde, wie es war.
Andere Tipps
Hier ist eine Funktion, die Sie verwenden, nutzen könnten str
mit unicode
Typen aus dem decodierten Ausgang von PyYAML
ersetzt werden:
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]})