Estoy tirando de los datos de un documento de Google, el procesamiento, y escribir en un archivo (que con el tiempo voy a pegar en una página WordPress).

Tiene algunos de los símbolos ASCII. ¿Cómo puedo convertir estos de forma segura a los símbolos que pueden ser utilizados en el código fuente HTML?

Actualmente me estoy convirtiendo todo a Unicode en el camino, uniendo a todos juntos en una cadena Python, a continuación, haciendo:

import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))

Hay un error de codificación en la última línea:

UnicodeDecodeError: ‘ascii’ codec no puede decodificar byte 0xa0 en la posición
12286: ordinal no en el rango de(128)

Solución parcial:

Esta Python se ejecuta sin error:

row = [unicode(x.strip()) if x is not None else u'' for x in row]
all_html = row[0] + "<br/>" + row[1]
f = open('out.txt', 'w')
f.write(all_html.encode("utf-8"))

Pero entonces, si abro el real archivo de texto, veo un montón de símbolos como:

Qur’an 

Tal vez tengo que escribir algo que no sea un archivo de texto?

  • El programa que se está usando para abrir no es interpretar el texto UTF-8 correctamente. Debería haber una opción para abrir el archivo como UTF-8.
InformationsquelleAutor simon | 2011-05-18

8 Comentarios

  1. 314

    Tratar exclusivamente con unicode objetos tanto como sea posible mediante la decodificación de las cosas a unicode objetos cuando llegue a ellos y a la codificación de ellos como sea necesario en el camino de salida.

    Si la cadena es en realidad un objeto unicode, usted necesita para convertir a un codificados en unicode objeto string antes de escribir en un archivo:

    foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
    f = open('test', 'w')
    f.write(foo.encode('utf8'))
    f.close()

    Cuando lea ese archivo de nuevo, usted obtendrá una codificado en unicode cadena que puede decodificar unicode objeto:

    f = file('test', 'r')
    print f.read().decode('utf8')
    • Gracias. Este se ejecuta sin error, pero luego si puedo abrir el archivo de texto, veo a un montón de extraños símbolos 🙂 tengo que copiar y pegar el texto en una página WordPress (no preguntar). Hay alguna manera de que pueda imprimir los símbolos que hay? Supongo que no a un archivo txt, derecha, pero tal vez a algo más?
    • Lo están utilizando para abrir el archivo de texto? Supongo que estás en Windows, y que va a abrir en el Bloc de notas, que no es demasiado inteligente con codificaciones. ¿Qué sucede cuando se abre en Wordpad?
    • ¿de dónde archivo método provienen?
  2. 68

    En Python 2.6+, podría usar io.open() que es el valor por defecto (builtin open()) en Python 3:

    import io
    
    with io.open(filename, 'w', encoding=character_encoding) as file:
        file.write(unicode_text)

    Podría ser más conveniente si usted necesita para escribir el texto de forma incremental (usted no necesita llamar a unicode_text.encode(character_encoding) varias veces). A diferencia de codecs módulo, io módulo tiene una adecuada universal de nuevas líneas de apoyo.

    • Hombre, he dedicado mucho tiempo para encontrar esto! Gracias!
    • Esto funciona para Python 3 también (obvio, pero todavía vale la pena señalar).
  3. 31

    Cadena Unicode manejo ya está estandarizado en Python 3.

    1. char s ya están almacenados en Unicode (32 bits) en la memoria
    2. Sólo necesitas abrir el archivo en utf-8

      (32-bit Unicode para la variable byte de longitud utf-8 la conversión se realiza automáticamente de la memoria al archivo).

      out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
      fobj = open("t1.txt", "w", encoding="utf-8")
      fobj.write(out1)
      fobj.close()
    • Pero esto no funciona en Python 2, a la derecha? (Me dijo que, en esto de Python 3 código, se ve tan concisa y razonable)
    • no debe trabajar en Python 2. Nos quedamos en Python 3. 3 es mucho mejor.
  4. 18

    El archivo abierto por codecs.open es un archivo que lleva unicode de datos, lo codifica en iso-8859-1 y los escribe en el archivo. Sin embargo, lo que intenta escribir no es unicode; tomar unicode y codificarla en iso-8859-1 mismo. Eso es lo que la unicode.encode método, y el resultado de la codificación de una cadena unicode es un bytestring (un str tipo.)

    Debería uso normal open() y codificación de unicode a ti mismo, o (generalmente una mejor idea) uso codecs.open() y no codificar los datos usted mismo.

  5. 15

    Prefacio: ¿su visor de trabajo?

    Asegúrese de que su visor/editor/terminal (sin embargo usted está interactuando con su codificados en utf-8 archivo) puede leer el archivo. Esto es con frecuencia un problema en Windows, por ejemplo, el Bloc de notas.

    Escritura de texto Unicode en un archivo de texto?

    En Python 2, uso open de la io módulo (este es el mismo que el grupo builtin open en Python 3):

    import io

    Las mejores prácticas, en general, el uso de UTF-8 para escribir los archivos (que ni siquiera tiene que preocuparse de orden de bytes con utf-8).

    encoding = 'utf-8'

    utf-8 es el más moderno y utilizable universalmente codificación – funciona en todos los navegadores web, la mayoría de editor de texto (consulte la configuración si usted tiene problemas) y la mayoría de terminales/shells.

    En Windows, usted puede tratar de utf-16le si usted está limitado a la salida de visualización en el Bloc de notas (o cualquier otra limitado visor).

    encoding = 'utf-16le' # sorry, Windows users... :(

    Y abrirlo con el contexto del administrador y escribir los caracteres unicode a cabo:

    with io.open(filename, 'w', encoding=encoding) as f:
        f.write(unicode_object)

    Ejemplo con muchos caracteres Unicode

    Aquí un ejemplo en el que los intentos de mapa de todos los caracteres posibles de hasta tres bits de ancho (4 es el máximo, pero eso sería ir demasiado lejos) de la representación digital (en enteros) a un codificados imprimible de salida, junto con su nombre, si es posible (poner esto en un archivo llamado uni.py):

    from __future__ import print_function
    import io
    from unicodedata import name, category
    from curses.ascii import controlnames
    from collections import Counter
    
    try: # use these if Python 2
        unicode_chr, range = unichr, xrange
    except NameError: # Python 3
        unicode_chr = chr
    
    exclude_categories = set(('Co', 'Cn'))
    counts = Counter()
    control_names = dict(enumerate(controlnames))
    with io.open('unidata', 'w', encoding='utf-8') as f:
        for x in range((2**8)**3): 
            try:
                char = unicode_chr(x)
            except ValueError:
                continue # can't map to unicode, try next x
            cat = category(char)
            counts.update((cat,))
            if cat in exclude_categories:
                continue # get rid of noise & greatly shorten result file
            try:
                uname = name(char)
            except ValueError: # probably control character, don't use actual
                uname = control_names.get(x, '')
                f.write(u'{0:>6x} {1}    {2}\n'.format(x, cat, uname))
            else:
                f.write(u'{0:>6x} {1}  {2}  {3}\n'.format(x, cat, char, uname))
    # may as well describe the types we logged.
    for cat, count in counts.items():
        print('{0} chars of category, {1}'.format(count, cat))

    Esta se debe ejecutar en el orden de alrededor de un minuto, y usted puede ver el archivo de datos, y si su visor de archivos pueden mostrar unicode, lo van a ver. Información acerca de las categorías se puede encontrar aquí. Basado en la cuenta, probablemente podemos mejorar nuestros resultados mediante la exclusión de la Cn y Co categorías, las cuales no tienen los símbolos asociados con ellos.

    $ python uni.py

    Se mostrará el hexadecimal de asignación, categoría, símbolo (a menos que no se puede obtener el nombre, así que probablemente un carácter de control), y el nombre del símbolo. por ejemplo,

    Recomiendo less en Unix o Cygwin (no imprimir/gato el archivo completo para su salida):

    $ less unidata

    por ejemplo, mostrará similares a las siguientes líneas que probé usando Python 2 (unicode 5.2):

         0 Cc NUL
        20 Zs     SPACE
        21 Po  !  EXCLAMATION MARK
        b6 So    PILCROW SIGN
        d0 Lu  Ð  LATIN CAPITAL LETTER ETH
       e59 Nd    THAI DIGIT NINE
      2887 So    BRAILLE PATTERN DOTS-1238
      bc13 Lo    HANGUL SYLLABLE MIH
      ffeb Sm    HALFWIDTH RIGHTWARDS ARROW

    Mi Python 3.5 de la Anaconda tiene unicode 8.0, yo presumiría que la mayoría de los 3 sería.

  6. 3

    Cómo imprimir caracteres unicode en un archivo:

    Guardar este archivo: foo.py:

    #!/usr/bin/python -tt
    # -*- coding: utf-8 -*-
    import codecs
    import sys 
    UTF8Writer = codecs.getwriter('utf8')
    sys.stdout = UTF8Writer(sys.stdout)
    print(u'e with obfuscation: é')

    Ejecutar y salida de la tubería de archivo:

    python foo.py > tmp.txt

    Abierto tmp.txt y mirar en el interior, ves esto:

    [email protected]:~$ cat tmp.txt 
    e with obfuscation: é

    Así ha guardado unicode e con una ofuscación de la marca en un archivo.

    • Yo estaba muy entusiasmado acerca de esta respuesta, pero da un error en mi máquina. Cuando puedo copiar/pegar el código, me sale un error: «TypeError: debe ser str, no en bytes»
  7. 1

    Que el error se produce cuando intenta codificar una cadena unicode: intenta decodificar, asumiendo que es en formato ASCII. Hay dos posibilidades:

    1. Estás codificación en un bytestring, pero debido a que usted ha utilizado codecs.abierto, el método de la escritura espera un objeto unicode. Así que lo codifica, y se intenta descodificar de nuevo. Probar: f.write(all_html) lugar.
    2. all_html no es, en efecto, un objeto unicode. Al hacer .encode(...), primero intenta decodificar.
  8. 0

    En el caso de la escritura en python3

    >>> a = u'bats\u00E0'
    >>> print a
    batsà
    >>> f = open("/tmp/test", "w")
    >>> f.write(a)
    >>> f.close()
    >>> data = open("/tmp/test").read()
    >>> data
    'batsà'

    En el caso de la escritura en python2:

    >>> a = u'bats\u00E0'
    >>> f = open("/tmp/test", "w")
    >>> f.write(a)
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

    Para evitar este error que habría que codificar a bytes usando codecs «utf-8» como este:

    >>> f.write(a.encode("utf-8"))
    >>> f.close()

    y decodificar los datos, mientras que la lectura usando los codecs «utf-8»:

    >>> data = open("/tmp/test").read()
    >>> data.decode("utf-8")
    u'bats\xe0'

    Y también si intenta ejecutar de impresión en esta cadena automáticamente decodificar el uso de la «utf-8» codecs como este

    >>> print a
    batsà

Dejar respuesta

Please enter your comment!
Please enter your name here