Python 笔记(一)字典与json使用及注意点

时间:2021-07-08 03:11:06

个人笔记系列,随便参考

1、python 中字典与json的差别

字典的生成

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})

 

Python的字典和JSON在表现形式上非常相似

Python中的一个字典 dic = { 'str': 'this is a string', 'list': [1, 2, 'a', 'b'], 'sub_dic': { 'sub_str': 'this is sub str', 'sub_list': [1, 2, 3] }, 'end': 'end' }

JSON对象 json_obj
= { 'str': 'this is a string', 'arr': [1, 2, 'a', 'b'], 'sub_obj': { 'sub_str': 'this is sub str', 'sub_list': [1, 2, 3] }, 'end': 'end' }

 

实际上JSON就是Python字典的字符串表示,但是字典作为一个复杂对象是无法直接转换成定义它的代码的字符串
字典是一个数据的结构,而json只是一个具有一定规则的字符串,方便在不同平台上处理其中包含的数据

但本质上来讲,字典是一种数据结构,json是一种格式;字典有很多内置函数,有多种调用方法,而json是数据打包的一种格式,并不像字典具备操作性,并且是格式就会有一些形式上的限制,比如json的格式要求必须且只能使用双引号作为key或者值的边界符号,不能使用单引号,而且“key”必须使用边界符(双引号),但字典就无所谓了。

  形式上的相近也让python提供了json.loads()转换函数,方便json数据的调用。 
  使用方法如下:

import json
a
=json.loads('{"a":"1","b":"2"}')
print a

2、python 中pickle与json的差别
# 1:Json的存数据到文件:

import json

info
= {
"name":"hjc",
"age":22
}
with open(
"a1.txt","w",encoding="utf-8") as f:
f.write(json.dumps(info)) # 注意!!!此处json存数据时会使用unicode的16进制格式,所以中文在保存文件中是\u开头的
                  # 当使用json.load()时会自动逆向识别,转成可读中文,大概为了不同平台的数据交流
                  # 若想保留中文的显示,可以添加参数ensure_ascii = False,文件中即可保留中文
# 2.Json的取数据
import json
with open(
"a1.txt","r",encoding="utf-8") as f:
data
= json.loads(f.readline())
print(data["age"])

# 3.Pickle的存数据
import pickle

def func():
print("hello tomorrow!!!")

info
= {
"name" : "hjc",
"age" : 24,
"hobby" : func
}
with open(
"a1.txt","wb") as f:
f.write(pickle.dumps(info))

# 4.Pickle的取数据:
import pickle

def func():
print("hello tomorrow!!!")

with open(
"a1.txt","rb") as f:
data
= pickle.loads(f.read())
data[
"hobby"]()

# 5 字典直接保存为文件(不推荐)

info = {
"name" : "hjc",
"age" : 24,
"hobby" : func
}
with open("a1.txt","w") as f:
f.write(str(info)) # 能够直接保存中文,但是无法直接当作json文件来使用loads(),因为保存的是单引号,json使用双引号。

 

json与字典的编码问题

以下内容摘抄自Python 3中的json.dumps,会将中文转换为unicode编码后保存

 

先把这次踩坑的结论放在最前面

1. Python 3已经将unicode作为默认编码

2. Python 3中的json在做dumps操作时,会将中文转换成unicode编码,并以16进制方式存储,再做逆向操作时,会将unicode编码转换回中文

这就解释了,为什么json.dumps操作后,得到的字符串是\uXXXX。

 

------------------分割线以下部分纯属扯淡,没时间的现在可以关闭页面了-------------------------

 

如果不知道上面两点,加之python之前对编码处理的不好名声,就会陷入一个问题深坑中。

读到这里,如果你赶时间,就可以不用往下看了。

爆出问题的代码如下:

@app.route("/<desc>/<amount>")

def addSimpleRecord(desc, amount):

    .....

        file.write(json.dumps(buildJson(desc, amount)));

    ....

整个程序运行正常,但当我打开文件看到保存的中文数据变成了\uXXXX时,头都大了。

经过了各种尝试,我发现网上对python3中的编码问题进行了如下归纳

  1. \uXXXX是unicode 16进制编码的表现形式
  2. 在文件的第一行加上# -*- coding: utf-8 -*-
  3. 对字符串对象进行str.decode('...').encode('...')
  4. 对字符串对象进行操作:str.encode('utf-8').decode('unicode_escape')

关于第一条,print("你" == "\u4f60")得到的结果是True

关于第二条,那是python2的故事,在python3中默认的文件编码就是utf-8。因此,在保存python 3的脚本时,请务必保存为utf-8。

关于第三条,那也是python2的故事,在ptyon3中,字符串默认采用unicode编码。

关于第四条,最初我是参考 python3 把\u开头的unicode转中文,把str形态的unicode转中文 ,发现不能重现,后来当我用\\uXXXX时,就重现了这篇文章中描述的问题,因为\在python字符串中起转义作用(我居然给忘记了)。

 

为什么json.dumps处理过后的中文就变成了\uXXXX呢?原因在这里py_encode_basestring_ascii

 

[python]  view plain  copy
 
  1. ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')  
  2. HAS_UTF8 = re.compile(b'[\x80-\xff]')  
  3. ESCAPE_DCT = {  
  4.     '\\': '\\\\',  
  5.     '"''"': '\\"', 
  6.     '\b': '\\b', 
  7.     '\f': '\\f', 
  8.     '\n': '\\n', 
  9.     '\r': '\\r', 
  10.     '\t': '\\t', 
  11.  
  12. def py_encode_basestring_ascii(s): 
  13.     """Return an ASCII-only JSON representation of a Python string 
  14.     """ 
  15.     def replace(match): 
  16.         s = match.group(0) 
  17.         try: 
  18.             return ESCAPE_DCT[s] 
  19.         except KeyError: 
  20.             n = ord(s) 
  21.             if n < 0x10000: 
  22.                 return '\\u{0:04x}'.format(n) 
  23.                 #return '\\u%04x' % (n,) 
  24.             else: 
  25.                 # surrogate pair 
  26.                 n -= 0x10000 
  27.                 s1 = 0xd800 | ((n >> 10) & 0x3ff) 
  28.                 s2 = 0xdc00 | (n & 0x3ff) 
  29.                 return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) 
  30.     return '"' + ESCAPE_ASCII.sub(replace, s) + '"'  

 

关键的地方就在:

return '\\u{0:04x}'.format(n)

其中{0:04x}表示取第一个参数,并取长度为4的16进制小写数字。

json.dumps的参数中有一个参数ensure_ascii,其默认值为True。我想这么做的目的可能是为了跨平台的通用性。

 

python3 把unicode转中文,把str形态的unicode转中文 
今天用py3.5爬东西的时候,爬到的是json格式,里面的中文还都是unicode的形式. 
讲道理的话只要直接输出就可以了,类似这样的

>>> print ("\u751F\u5316\u5371\u673A")
生化危机
>>>

软而坑爹的是他返回的匹配的list是这样的

['\\u751F\\u5316\\u5371\\u673A']

结果print出来事这样的

>>> print (a[0])
\u751F\u5316\u5371\u673A
>>>

python3以上取消了decode,所以你直接想st.decode(“utf-8”)的话会报str没有decode方法的错 
最后贴一下解决方案

>>> print (a[0].encode('utf-8').decode('unicode_escape'))
生化危机
>>>

到此为止,python 3的编码问题总算是告一段落,如有问题,欢迎交流。