python - print - Guardando los textos de utf-8 en json.dumps como UTF8, no como secuencia de escape / u
python string to json (8)
Código de muestra:
>>> import json
>>> json_string = json.dumps("ברי צקלה")
>>> print json_string
"/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4"
El problema: no es legible por humanos. Mis usuarios (inteligentes) desean verificar o incluso editar archivos de texto con volcados JSON. (y prefiero no usar XML)
¿Hay una manera de serializar objetos en la cadena utf-8 json (en lugar de / uXXXX)?
esto no ayuda
>>> output = json_string.decode(''string-escape'')
"/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4"
esto funciona, pero si alguno de los subobjetos es un Python-Unicode y no utf-8, volcará basura:
>>> #### ok:
>>> s= json.dumps( "ברי צקלה", ensure_ascii=False)
>>> print json.loads(s)
ברי צקלה
>>> #### NOT ok:
>>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" }
>>> print d
{1: ''/xd7/x91/xd7/xa8/xd7/x99 /xd7/xa6/xd7/xa7/xd7/x9c/xd7/x94'',
2: u''/xd7/x91/xd7/xa8/xd7/x99 /xd7/xa6/xd7/xa7/xd7/x9c/xd7/x94''}
>>> s = json.dumps( d, ensure_ascii=False, encoding=''utf8'')
>>> print json.loads(s)[''1'']
ברי צקלה
>>> print json.loads(s)[''2'']
××¨× ×¦×§××
ACTUALIZACIÓN: Esta es una respuesta incorrecta, pero aún así es útil entender por qué está mal. Ver comentarios.
¿Qué tal unicode-escape
?
>>> d = {1: "ברי צקלה", 2: u"ברי צקלה"}
>>> json_str = json.dumps(d).decode(''unicode-escape'').encode(''utf8'')
>>> print json_str
{"1": "ברי צקלה", "2": "ברי צקלה"}
Aquí está mi solución usando json.dump ():
def jsonWrite(p, pyobj, ensure_ascii=False, encoding=SYSTEM_ENCODING, **kwargs):
with codecs.open(p, ''wb'', ''utf_8'') as fileobj:
json.dump(pyobj, fileobj, ensure_ascii=ensure_ascii,encoding=encoding, **kwargs)
donde SYSTEM_ENCODING se establece en:
locale.setlocale(locale.LC_ALL, '''')
SYSTEM_ENCODING = locale.getlocale()[1]
El siguiente es mi comprensión var leer la respuesta anterior y google.
# coding:utf-8
r"""
@update: 2017-01-09 14:44:39
@explain: str, unicode, bytes in python2to3
#python2 UnicodeDecodeError: ''ascii'' codec can''t decode byte 0xe4 in position 7: ordinal not in range(128)
#1.reload
#importlib,sys
#importlib.reload(sys)
#sys.setdefaultencoding(''utf-8'') #python3 don''t have this attribute.
#not suggest even in python2 #see:http://.com/questions/3828723/why-should-we-not-use-sys-setdefaultencodingutf-8-in-a-py-script
#2.overwrite /usr/lib/python2.7/sitecustomize.py or (sitecustomize.py and PYTHONPATH=".:$PYTHONPATH" python)
#too complex
#3.control by your own (best)
#==> all string must be unicode like python3 (u''xx''|b''xx''.encode(''utf-8'')) (unicode ''s disappeared in python3)
#see: http://blog.ernest.me/post/python-setdefaultencoding-unicode-bytes
#how to Saving utf-8 texts in json.dumps as UTF8, not as /u escape sequence
#http://.com/questions/18337407/saving-utf-8-texts-in-json-dumps-as-utf8-not-as-u-escape-sequence
"""
from __future__ import print_function
import json
a = {"b": u"中文"} # add u for python2 compatibility
print(''%r'' % a)
print(''%r'' % json.dumps(a))
print(''%r'' % (json.dumps(a).encode(''utf8'')))
a = {"b": u"中文"}
print(''%r'' % json.dumps(a, ensure_ascii=False))
print(''%r'' % (json.dumps(a, ensure_ascii=False).encode(''utf8'')))
# print(a.encode(''utf8'')) #AttributeError: ''dict'' object has no attribute ''encode''
print('''')
# python2:bytes=str; python3:bytes
b = a[''b''].encode(''utf-8'')
print(''%r'' % b)
print(''%r'' % b.decode("utf-8"))
print('''')
# python2:unicode; python3:str=unicode
c = b.decode(''utf-8'')
print(''%r'' % c)
print(''%r'' % c.encode(''utf-8''))
"""
#python2
{''b'': u''/u4e2d/u6587''}
''{"b": "//u4e2d//u6587"}''
''{"b": "//u4e2d//u6587"}''
u''{"b": "/u4e2d/u6587"}''
''{"b": "/xe4/xb8/xad/xe6/x96/x87"}''
''/xe4/xb8/xad/xe6/x96/x87''
u''/u4e2d/u6587''
u''/u4e2d/u6587''
''/xe4/xb8/xad/xe6/x96/x87''
#python3
{''b'': ''中文''}
''{"b": "//u4e2d//u6587"}''
b''{"b": "//u4e2d//u6587"}''
''{"b": "中文"}''
b''{"b": "/xe4/xb8/xad/xe6/x96/x87"}''
b''/xe4/xb8/xad/xe6/x96/x87''
''中文''
''中文''
b''/xe4/xb8/xad/xe6/x96/x87''
"""
El uso de asegurar_ascii = Falso en json.dumps es la dirección correcta para resolver este problema, como lo señaló Martijn. Sin embargo, esto puede provocar una excepción:
UnicodeDecodeError: ''ascii'' codec can''t decode byte 0xe7 in position 1: ordinal not in range(128)
Necesitas configuraciones adicionales en site.py o sitecustomize.py para configurar tu sys.getdefaultencoding () correctamente. site.py está en lib / python2.7 / y sitecustomize.py está en lib / python2.7 / site-packages.
Si desea usar site.py, en def setencoding (): cambie primero si 0: a si 1: para que Python use la configuración regional de su sistema operativo.
Si prefieres usar sitecustomize.py, puede que no exista si no lo has creado. simplemente ponga estas líneas:
import sys
reload(sys)
sys.setdefaultencoding(''utf-8'')
Luego, puede hacer algo de salida china json en formato utf-8, como:
name = {"last_name": u"王"}
json.dumps(name, ensure_ascii=False)
Obtendrá una cadena codificada en utf-8, en lugar de / u escape json string.
Para verificar su codificación predeterminada:
print sys.getdefaultencoding()
Debería obtener "utf-8" o "UTF-8" para verificar su configuración de site.py o sitecustomize.py.
Tenga en cuenta que no puede hacer sys.setdefaultencoding ("utf-8") en la consola interactiva de Python.
La solución temporal de python 2 de Peters falla en un caso de borde:
d = {u''keyword'': u''bad credit /xe7redit cards''}
with io.open(''filename'', ''w'', encoding=''utf8'') as json_file:
data = json.dumps(d, ensure_ascii=False).decode(''utf8'')
try:
json_file.write(data)
except TypeError:
# Decode data to Unicode first
json_file.write(data.decode(''utf8''))
UnicodeEncodeError: ''ascii'' codec can''t encode character u''/xe7'' in position 25: ordinal not in range(128)
Se estrelló en la parte .decode (''utf8'') de la línea 3. Solucioné el problema simplificando el programa al evitar ese paso y la carcasa especial de ascii:
with io.open(''filename'', ''w'', encoding=''utf8'') as json_file:
data = json.dumps(d, ensure_ascii=False, encoding=''utf8'')
json_file.write(unicode(data))
cat filename
{"keyword": "bad credit çredit cards"}
Use codecs si es posible,
with codecs.open(''file_path'', ''a+'', ''utf-8'') as fp:
fp.write(json.dumps(res, ensure_ascii=False))
Use el interruptor ensure_ascii=False
a json.dumps()
, luego codifique el valor a UTF-8 manualmente:
>>> json_string = json.dumps(u"ברי צקלה", ensure_ascii=False).encode(''utf8'')
>>> json_string
''"/xd7/x91/xd7/xa8/xd7/x99 /xd7/xa6/xd7/xa7/xd7/x9c/xd7/x94"''
>>> print json_string
"ברי צקלה"
Si está escribiendo esto en un archivo, puede usar io.open()
lugar de open()
para producir un objeto de archivo que codifique los valores de Unicode mientras escribe, luego use json.dump()
lugar de escribir en ese archivo :
with io.open(''filename'', ''w'', encoding=''utf8'') as json_file:
json.dump(u"ברי צקלה", json_file, ensure_ascii=False)
En Python 3, el open()
incorporado es un alias para io.open()
. Tenga en cuenta que hay un error en el módulo json
en el que ensure_ascii=False
flag puede producir una mezcla de objetos unicode
y str
. La solución para Python 2 es:
with io.open(''filename'', ''w'', encoding=''utf8'') as json_file:
data = json.dumps(u"ברי צקלה", ensure_ascii=False)
# unicode(data) auto-decodes data to unicode if str
json_file.write(unicode(data))
Si está pasando cadenas de bytes (escriba str
en Python 2, bytes
en Python 3) codificados a UTF-8, asegúrese de establecer también la palabra clave de encoding
:
>>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" }
>>> d
{1: ''/xd7/x91/xd7/xa8/xd7/x99 /xd7/xa6/xd7/xa7/xd7/x9c/xd7/x94'', 2: u''/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4''}
>>> s=json.dumps(d, ensure_ascii=False, encoding=''utf8'')
>>> s
u''{"1": "/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4", "2": "/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4"}''
>>> json.loads(s)[''1'']
u''/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4''
>>> json.loads(s)[''2'']
u''/u05d1/u05e8/u05d9 /u05e6/u05e7/u05dc/u05d4''
>>> print json.loads(s)[''1'']
ברי צקלה
>>> print json.loads(s)[''2'']
ברי צקלה
Tenga en cuenta que su segunda muestra no es unicode válida; le dio UTF-8 bytes como un literal Unicode, que nunca funcionaría:
>>> s = u''/xd7/x91/xd7/xa8/xd7/x99 /xd7/xa6/xd7/xa7/xd7/x9c/xd7/x94''
>>> print s
××¨× ×¦×§××
>>> print s.encode(''latin1'').decode(''utf8'')
ברי צקלה
Solo cuando codifiqué esa cadena a Latín 1 (cuyos puntos de código Unicode se asignan de uno a uno a bytes) y luego los decodifico como UTF-8, se ve el resultado esperado. Eso no tiene nada que ver con JSON y todo lo relacionado con que se use la entrada incorrecta. El resultado se llama un Mojibake .
Si obtuviste ese valor Unicode de un literal de cadena, se decodificó utilizando el códec incorrecto. Puede ser que su terminal esté mal configurado o que su editor de texto haya guardado su código fuente utilizando un códec diferente al que le dijo a Python que leyera el archivo. O lo obtuviste de una biblioteca que aplicó el códec incorrecto. Todo esto no tiene nada que ver con la biblioteca JSON .
fácil como un pastel
Escribir en un archivo
import codecs
import json
with codecs.open(''your_file.txt'', ''w'', encoding=''utf-8'') as f:
json.dump({"message":"xin chào việt nam"}, f, ensure_ascii=False)
Para imprimir a stdin
import codecs
import json
print(json.dumps({"message":"xin chào việt nam"}, ensure_ascii=False))