Pregunta

Las cargas de paquetes PyYAML cadenas sin marcar como Unicode o str objetos, en función de su contenido.

Me gustaría utilizar objetos Unicode a través de mi programa (y, por desgracia, no se puede cambiar a Python 3 por el momento).

¿Hay una manera fácil de forzar a PyYAML siempre cadenas objetos Unicode carga? No quiero que el desorden de mi YAML con etiquetas !!python/unicode.

# Encoding: UTF-8

import yaml

menu= u"""---
- spam
- eggs
- bacon
- crème brûlée
- spam
"""

print yaml.load(menu)

Salida: ['spam', 'eggs', 'bacon', u'cr\xe8me br\xfbl\xe9e', 'spam']

Me gustaría: [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']

¿Fue útil?

Solución

Aquí hay una versión que anula el manejo de cadenas por PyYAML siempre unicode salida. En realidad, este es probablemente el resultado idéntico de la otra respuesta que he publicado, excepto más corto (es decir, que todavía tienen que asegurarse de que las cadenas en clases personalizadas se convierten en unicode o se pasan cadenas unicode a sí mismo si utiliza controladores personalizados):

# -*- 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
""")

(Lo anterior da [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam'])

No he probado en LibYAML (el analizador basado en c) ya que no podía compilarlo sin embargo, así que voy a dejar la otra respuesta como estaba.

Otros consejos

Esta es una función que podría utilizar para usar para reemplazar str con tipos unicode desde la salida decodificada del 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]})
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top