Estoy tratando de registro de una codificación UTF-8 de la cadena en un archivo utilizando Python registro de paquete. Como un juguete ejemplo:

import logging

def logging_test():
    handler = logging.FileHandler("/home/ted/logfile.txt", "w",
                                  encoding = "UTF-8")
    formatter = logging.Formatter("%(message)s")
    handler.setFormatter(formatter)
    root_logger = logging.getLogger()
    root_logger.addHandler(handler)
    root_logger.setLevel(logging.INFO)

    # This is an o with a hat on it.
    byte_string = '\xc3\xb4'
    unicode_string = unicode("\xc3\xb4", "utf-8")

    print "printed unicode object: %s" % unicode_string

    # Explode
    root_logger.info(unicode_string)

if __name__ == "__main__":
    logging_test()

Este explota con UnicodeDecodeError en el logging.info() la llamada.

A un nivel inferior, el de Python registro de paquete está utilizando el paquete de codecs para abrir el archivo de registro, pasando el «UTF-8» argumento como el de la codificación. Eso es todo bien y bueno, pero tratando de escribir cadenas de bytes al archivo en lugar de unicode objetos, que explota. Esencialmente, Python es hacer esto:

file_handler.write(unicode_string.encode("UTF-8"))

Cuando debería estar haciendo esto:

file_handler.write(unicode_string)

Es esto un error en Python, o estoy tomando loco pastillas? FWIW, esta es una acción de Python 2.6 instalación.

  • El código funciona perfectamente bien aquí. Traté de hacerla fracasar, pero no lo he conseguido.
  • Y tienes razón, python es la codificación de los mismos con UTF-8, porque pide el outfile lo que la codificación a utilizar, y se especifica la codificación UTF-8, así que eso es todo y bien.
  • Tuve que golpear la wayback machine para encontrar el ejemplo usted ha mencionado. Interesante.
InformationsquelleAutor Ted Dziuba | 2009-10-09

5 Comentarios

  1. 15

    Comprobar que tienes la última Python 2.6 – algunos Unicode bugs que se han encontrado y corregido desde 2.6 salió. Por ejemplo, en mi Ubuntu Jaunty sistema, me encontré con su secuencia de comandos de copiar y pegar, eliminar sólo la » /home/ted/’ prefijo del nombre de archivo de registro. Resultado (copiado y pegado desde una ventana de terminal):

    [email protected]:~/proyectos/scratch$ python --version 
    Python 2.6.2 
    [email protected]:~/proyectos/scratch$ python utest.py 
    impreso unicode objeto: ô 
    [email protected]:~/proyectos/scratch$ cat logfile.txt 
    ô 
    [email protected]:~/proyectos/scratch$ 
    

    En un cuadro de Windows:

    C:\temp> --version de python 
    Python 2.6.2 
    
    C:\temp>python utest.py 
    impreso unicode objeto: ô 
    

    Y el contenido del archivo:

    UTF-8 En Python registro, ¿cómo?

    Esto también podría explicar por qué Lennart Regebro no podía reproducir bien.

    • Sí, esta era. Hubo un error en el python registro de paquete que se fija en una versión posterior.
    • Estoy ejecutando Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) [GCC 4.2.1 (Apple Inc. construir 5646)], en darwin, en mi iMac, y me sigue apareciendo el mismo error. Fue el error realmente fijo?
    • Sí, lo fue – ocurrió entre 2.6.1 y 2.6.2, en la revisión 69448: svn.python.org/view?view=rev&la revisión=69448 – entonces usted necesita para actualizar a una revisión posterior.
  2. 28

    Tener un código como:

    raise Exception(u'щ')

    Causado:

      File "/usr/lib/python2.7/logging/__init__.py", line 467, in format
        s = self._fmt % record.__dict__
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

    Esto sucede porque la cadena de formato es una cadena de bytes, mientras que algunos de la cadena de formato argumentos son unicode cadenas de caracteres que no son ASCII:

    >>> "%(message)s" % {'message': Exception(u'\u0449')}
    *** UnicodeEncodeError: 'ascii' codec can't encode character u'\u0449' in position 0: ordinal not in range(128)

    De decisiones de la cadena de formato unicode corrige el problema:

    >>> u"%(message)s" % {'message': Exception(u'\u0449')}
    u'\u0449'

    Así, en el registro de configuración de formato de toda la cadena de unicode:

    'formatters': {
        'simple': {
            'format': u'%(asctime)-s %(levelname)s [%(name)s]: %(message)s',
            'datefmt': '%Y-%m-%d %H:%M:%S',
        },
     ...

    Parche y el defecto logging formateador de utilizar unicode cadena de formato:

    logging._defaultFormatter = logging.Formatter(u"%(message)s")
    • ¿Qué acerca de Python 3.5? No todas las cadenas se unicode por defecto?
    • ¿tienes el mismo problema con Python 3
    • Sí, lo hice en la ventana acoplable contenedor. Lo resuelto por la configuración de un montón de env variables conectadas a os de codificación. Para cualquier persona tropezando aquí con el mismo problema, consulte stackoverflow.com/a/27931669/260480.
    • Yo en mi código import locale; if locale.getpreferredencoding().upper() != 'UTF-8': locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
  3. 3

    He tenido un problema similar correr Django en Python3: Mi registrador murió después de encontrar algunos Diéresis (äöüß), pero fue bien. Miré a través de una gran cantidad de resultados y no encontró ninguno de trabajo. Traté de

    import locale; 
    if locale.getpreferredencoding().upper() != 'UTF-8': 
        locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') 

    que me de el comentario anterior.
    No trabajo. Mirando la configuración regional actual me dio un poco de locos ANSI cosa, que resultó significa básicamente «ASCII». Que me envió totalmente en la dirección equivocada.

    Cambiar el formato de registro-cadenas Unicode no ayudaría.
    Configuración de una magia de codificación de comentario al principio de la secuencia de comandos no ayudaría.
    Ajuste el juego de caracteres en el mensaje del remitente (el texto provenía de un HTTP-reqeust) no ayuda.

    ¿Qué trabajo se ajuste a la codificación en el archivo de controlador para UTF-8 en settings.py. Porque yo no tenía nada establecido, el defecto sería None. Que al parecer termina siendo ASCII (o como me gustaría pensar: CULO-CLAVE)

        'handlers': {
            'file': {
                'level': 'DEBUG',
                'class': 'logging.handlers.TimedRotatingFileHandler',
                'encoding': 'UTF-8', # <-- That was missing.
                ....
            },
        },
  4. 2

    Intente esto:

    import logging
    
    def logging_test():
        log = open("./logfile.txt", "w")
        handler = logging.StreamHandler(log)
        formatter = logging.Formatter("%(message)s")
        handler.setFormatter(formatter)
        root_logger = logging.getLogger()
        root_logger.addHandler(handler)
        root_logger.setLevel(logging.INFO)
    
        # This is an o with a hat on it.
        byte_string = '\xc3\xb4'
        unicode_string = unicode("\xc3\xb4", "utf-8")
    
        print "printed unicode object: %s" % unicode_string
    
        # Explode
        root_logger.info(unicode_string.encode("utf8", "replace"))
    
    
    if __name__ == "__main__":
        logging_test()

    Para qué vale el que yo estaba esperando a tener el uso de codecs.abrir para abrir el archivo con codificación utf-8, pero ya que el defecto o algo más está pasando aquí, ya que funciona como es como este.

    • NameError: nombre global ‘unicode’ no está definido
    • usted está usando python 3 supongo
  5. 1

    Si he entendido tu problema correctamente, el mismo problema que surgiera en su sistema cuando se acaba:

    str(u'ô')

    Supongo codificación automática para la configuración regional de codificación en Unix no funcionará hasta que se ha habilitado la configuración regional if rama en la setencoding función en su sitio módulo a través de locale. Este archivo normalmente se encuentra en /usr/lib/python2.x, vale la pena la inspección de todos modos. AFAIK, la configuración regional setencoding está deshabilitada de forma predeterminada (es verdad para mi Python 2.6 instalación).

    Las opciones son:

    • Dejar que el sistema de averiguar la forma correcta de codificar Unicode cadenas de bytes o hacerlo en el código (algunas de configuración en el sitio específico de site.py es necesario)
    • Codificar cadenas Unicode en el código y de salida sólo bytes

    Ver también La Ilusoria setdefaultencoding por Ian Bicicleta y enlaces relacionados.

Dejar respuesta

Please enter your comment!
Please enter your name here