Scrivi a file di UTF-8 in Python
-
06-09-2019 - |
Domanda
Sono molto confuso con il codecs.open function
. Quando faccio:
file = codecs.open("temp", "w", "utf-8")
file.write(codecs.BOM_UTF8)
file.close()
E mi dà l'errore
UnicodeDecodeError: codec 'ascii' non può decodificare 0xEF byte in posizione 0: ordinale non nel campo (128)
Se faccio:
file = open("temp", "w")
file.write(codecs.BOM_UTF8)
file.close()
Funziona bene.
Domanda è il motivo per cui fa il primo metodo fallire? E come faccio a inserire il bom?
Se il secondo metodo è il modo corretto di farlo, ciò che il punto di usare codecs.open(filename, "w", "utf-8")
?
Soluzione
Credo che il problema è che codecs.BOM_UTF8
è una stringa di byte, non una stringa Unicode. Ho il sospetto che il gestore di file sta cercando di indovinare che cosa si intende realmente sulla base di "Io sono destinata ad essere la scrittura come testo Unicode UTF-8-encoded, ma mi avete dato una stringa di byte!"
Provare a scrivere la stringa Unicode per il segno di ordine dei byte (cioè Unicode U + FEFF) direttamente, in modo che il file appena codifica che, come UTF-8:
import codecs
file = codecs.open("lol", "w", "utf-8")
file.write(u'\ufeff')
file.close()
(Che sembra dare la risposta giusta -. Un file con i byte EF BB BF)
EDIT: S. Lott suggerimento di utilizzare "utf-8-SIG", come la codifica è uno migliore di esplicitamente scrivere la distinta da soli, ma lascio questa risposta qui come spiega cosa stava succedendo sbagliato prima.
Altri suggerimenti
Leggi il seguente: http://docs.python.org/ biblioteca / codecs.html # modulo-encodings.utf_8_sig
A tale scopo
with codecs.open("test_output", "w", "utf-8-sig") as temp:
temp.write("hi mom\n")
temp.write(u"This has ♭")
Il file risultante è UTF-8 con il BOM previsto.
@ S-Lott dà la procedura corretta, ma in espansione sulle Unicode problemi, il Python interprete in grado di fornire ulteriori delucidazioni.
Jon Skeet è giusto (insolito) sulla codecs
modulo - contiene stringhe di byte:
>>> import codecs
>>> codecs.BOM
'\xff\xfe'
>>> codecs.BOM_UTF8
'\xef\xbb\xbf'
>>>
Picking un'altra nit, il BOM
ha uno standard Unicode nome, e può essere inserito come:
>>> bom= u"\N{ZERO WIDTH NO-BREAK SPACE}"
>>> bom
u'\ufeff'
E 'accessibile anche tramite unicodedata
:
>>> import unicodedata
>>> unicodedata.lookup('ZERO WIDTH NO-BREAK SPACE')
u'\ufeff'
>>>
Io uso il comando file * nix per convertire un file charset sconosciuto in un file UTF-8
# -*- encoding: utf-8 -*-
# converting a unknown formatting file in utf-8
import codecs
import commands
file_location = "jumper.sub"
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)
file_stream = codecs.open(file_location, 'r', file_encoding)
file_output = codecs.open(file_location+"b", 'w', 'utf-8')
for l in file_stream:
file_output.write(l)
file_stream.close()
file_output.close()