Python处理json,dict数据
json与dict的区别
Python 的dict是一种数据结构,json 是一种数据传输格式。json 就是一个根据某种约定格式编写的纯字符串,不具备任何数据结构的特征。而 python 的dict的字符串表现形式的规则看上去和 json 类似,但是dict本身是一个完整的数据结构,实现了一切自身该有的算法。
Python的dict的key可以是任意可hash对象,json只能是字符串。形式上有些相像,但json是纯文本的,无法直接操作。
json的格式要求必须且只能使用双引号作为key或者值的边界符号,不能使用单引号,而且"key"必须使用边界符(双引号),但dict就无所谓了。
python的dict的Key是唯一的,而json的Key可以重复。
python 的dict可以嵌套tuple, json里只有array。
json和dict在python里的转换方法
json在python中的数据处理:
1. 序列化: dic对象 ➡ json字符串(存储,传输) 编码
2. 反序列化:json ➡dic (分析,处理)解码
import json
json.loads() # 将json数据转化成dict数据
json.dumps() # 将dict数据转化成json数据
json.load() # 读取json文件数据,转成dict数据
json.dump() # 将dict数据转化成json数据后写入json文件
python 读写json
读取json文件,并转为dict
with open('.../XXX.json','r') as f:
data= json.load(f)
或者:
data = json.load(open('.../XXX.json','r'))
将dict数据转化为json,并写入json文件
with open('json_data.txt','w+') as f:
json.dump(dict_data,f)
python 处理dict数据
取键、值、键值对
# 字典在for迭代中默认只输出key
for k in dict_data:
print(k)
# 迭代输出key
for k in dict_data.keys():
print(k)
# 迭代输出value
for v in dict_data.values():
print(v)
# 迭代输出键值对
for k,v in dict_data.items():
print(k,v)
dict的增删改:
# 增加一个键值对:
dd['new_key'] = 'XXX'
# 改键值
dd['key'] = 'XX'
# 删除键值对
del['key'] # 删除字典第一层的键值对
del['key1']['key2']['key3'] # 删除多层嵌套里的键值对
dd.pop('key') # 删除键值对,并返回对应的value
# 判断是否为字典格式
isinstance(data,dict)
获取多层嵌套dict的键值对:
def get_all_dict(data):
if isinstance(data,dict):
for x in range(len(data)):
temp_key = list(data.keys())[x]
temp_value = data[temp_key]
print('KEY --> {}\nVALUE --> {}'.format(temp_key,temp_value))
print('\t')
get_all_dict(temp_value) # 迭代输出结果
对比两个字典的差异
dict1 = {'a':1,'b':2,'c':3,'d':4}
dict2 = {'a':1,'b':2,'c':5,'e':6}
differ = set(dict1.items()) ^ set(dict2.items())
print(differ)
#所有差异
#输出:{('c', 3), ('e', 6), ('c', 5), ('d', 4)}
diff = dict1.keys() & dict2
diff_vals = [(k, dict1[k], dict2[k]) for k in diff if dict1[k] != dict2[k]]
print(diff_vals)
#相同key,不同value
#输出:[('c', 3, 5)]
其他参考
a = {
"x":1,
"y":2,
"z":3
}
b = {
"x":1,
"w":11,
"z":12
}
print(a.items())
>>>dict_items([('x', 1), ('y', 2), ('z', 3)])
# 查看两个字典共有的key
print(a.keys() & b.keys())
>>>{'x', 'z'}
# 查看字典a 和字典b 的不共有的key
print(a.keys() ^ b.keys())
>>>{'y'}
# 查看在字典a里面而不在字典b里面的key
print(a.keys() - b.keys())
>>>{('x', 1)}
# 查看字典a和字典b相同的键值对
print(a.items() & b.items())
>>>{'w', 'y'}
json中None替换成null
import json
d = {"name":None}
s = json.dumps(d)
s = s.replace('null', '\"null\"')
d = json.loads(s)
print(d)
>> {'name':'null'}
其他说明:
在pandas中, 如果其他的数据都是数值类型, pandas会把None自动替换成NaN, 甚至能将s[s.isnull()]= None,和s.replace(NaN, None)操作的效果无效化。 这时需要用where函数才能进行替换。
None能够直接被导入数据库作为空值处理, 包含NaN的数据导入时会报错。
numpy和pandas的很多函数能处理NaN,但是如果遇到None就会报错。
None和NaN都不能被pandas的groupby函数处理,包含None或者NaN的组都会被忽略。
总之,None是python自带的,而NaN则是被numpy和pandas所支持的
等值性比较的总结:(True表示被判定为相等)
将字典list里的键由str转换为float
trip[0]:
{'pickup_latitude': '40.64499',
'pickup_longitude': '-73.78115',
'trip_distance': '18.38'}
处理方式:
for list_dict in list_of_dicts:
for key, value in list_dict.items():
list_dict[key] = float(value)
遍历在列表(list)中插入字典(dic)
nid = "1,2"
print(nid.split(','))
datas = []
for i in nid.split(','):
mydict = {}
mydict["id"] = str(i)
mydict["checked"] = True
datas.append(mydict)
print(str(datas))
输出:
['1', '2']
[{'id': '1', 'checked': True}, {'id': '2', 'checked': True}]
sql语句统计每行非空列个数
--空
select id , num =
(case when col1 is null then 1 else 0 end) +
(case when col2 is null then 1 else 0 end) +
(case when col3 is null then 1 else 0 end) +
(case when col4 is null then 1 else 0 end)
from tb
--非空
select id , num =
(case when col1 is not null then 1 else 0 end) +
(case when col2 is not null then 1 else 0 end) +
(case when col3 is not null then 1 else 0 end) +
(case when col4 is not null then 1 else 0 end)
from tb
项目中生成最多非空列的table
select id ,
case when filed !='' then 1 else 0 end as num
from ods_crd_ddt_external_dev.vira_ft_ods_issue_s3_di_pt vfoisdp order by num desc limit 10
两个列表转换成字典
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}
没有zip的写法
l1 = [1,2,3,4,5]
l2 = ['a','b','c','d','e']
d1 = {}
for l1_ in l1:
for l2_ in l2:
d1[l1_] = l2_
l2.remove(l2_)
break
print (d1)
{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}
取dict键组成列表
students = {
'小甲':18,
'小乙':20,
'小丙':15
}
1、只取字典的键,组成新的列表
b = [ key for key,value in students.items() ]
b = [ '小甲', '小乙','小丙' ]
2、字典的键值对互换,组成新的字典;
b = { value:key for key,value in students.items() }
b = {
18:'小甲',
20:'小乙',
15:'小丙'
}
将list写入到json文件里面 (list元素为字典)
[{'LT/C_score': 0.44917283324979085, 'class_uncertainty': 0.060122907161712646, 'image_id': 286849}, {'LT/C_score': 0.8943103022795436, 'class_uncertainty': 0.009622752666473389, 'image_id': 540932}, {'LT/C_score': 0.8732056996282929, 'class_uncertainty': 0.00022846460342407227, 'image_id': 32901}, {'LT/C_score': 0.8979904106858694, 'class_uncertainty': 0.002511739730834961, 'image_id': 324614}, {'LT/C_score': 0.8679021984870174, 'class_uncertainty': 0.0019818544387817383, 'image_id': 270474}, {'LT/C_score': 0.7331004226857969, 'class_uncertainty': 0.00713348388671875, 'image_id': 139}, {'LT/C_score': 0.11941635694217467, 'class_uncertainty': 0.0169374942779541, 'image_id': 241677}, {'LT/C_score': 0.02415653156423425, 'class_uncertainty': 0.014993846416473389, 'image_id': 528399}, {'LT/C_score': 0.1769359589898254, 'class_uncertainty': 0.2365768551826477, 'image_id': 565391}, {'LT/C_score': 0.866919080778817, 'class_uncertainty': 0.0014355778694152832, 'image_id': 196754}]
import json
import os
def write_list_to_json(list, json_file_name, json_file_save_path):
"""
将list写入到json文件
:param list:
:param json_file_name: 写入的json文件名字
:param json_file_save_path: json文件存储路径
:return:
"""
os.chdir(json_file_save_path)
with open(json_file_name, 'w') as f:
json.dump(list, f)
读取txt中的json数据
txt文本文件能存储各式各样数据,结构化的二维表、半结构化的json,非结构化的纯文本。
存储在excel、csv文件中的二维表,都是可以直接存储在txt文件中的。
半结构化的json也可以存储在txt文本文件中。
最常见的是txt文件中存储一群非结构化的数据:
从txt中读出json类型的半结构化数据
import pandas as pd
import json
f = open("../data/test.txt","r",encoding="utf-8")
data = json.load(f)
需要注意的是json必须是双引号:"" 才能操作
通过以下命令获取数据类型
type(data)
# print(type(data))
把Json文件按行读入,写入list(list中每行为字典数据)
有如下格式json文件
{"ID": "001", "name": "a", age: "12"}
{"ID": "002", "name": "b", age: "23"}
{"ID": "003", "name": "c", age: "42"}
...
将json文件按行转为字典数据并存入list
#!/usr/bin/python3
# coding=utf-8
import json
papers = [] # 该数组每行都是字典数据{}
file = open("E:\\pycharm1\\testset2.json", 'r', encoding = 'utf-8')
# 上面路径是我的json文件所在地,后面包含中文编码
for line in file.readlines():
dic = json.loads(line)
papers.append(dic)
以key "name"为例,对提取出的数据按照属性进行分析:
for line in range(0, len(papers)):
S1 = (papers[line])['name'] # 读取key为name的value
将list对象写入txt文件
list1 = ['1','2','3','4']
fileObject = open('list.txt','w')
for word in list1:
fileObject.write(word)
fileObject.write('\n')
fileObject.close()
txt文件读出
这里用open函数读取了一个txt文件,”encoding”表明了读取格式是“utf-8”,还可以忽略错误编码。
另外,使用with语句操作文件IO是个好习惯,省去了每次打开都要close()
with open("list.txt","r",encoding="utf-8",errors='ignore') as f:
data = f.readlines()
for line in data:
word = line.strip() #list
print(word)
读取数据为numpy的数组,可以进一步转换为list对象
array_ = numpy.loadtxt('list.txt')
list_ = list(array_)
读取TXT每行,并存到LIST中
例子1
这样去操作txt文件里的json数据会导致存入的都是str
方法一:
import sys
result=[]
with open('accounts.txt','r') as f:
for line in f:
result.append(list(line.strip('\n').split(',')))
print(result)
输出:
方法二:
处理数据:
第一步:读取文件中的数据
读取文件中的数据比较简单,代码运行如下:
读取文件后的数据,发现是这是些详细的字符串,可以通过打印来看下效果:
打印的结果比较像txt文本中的内容,但是在python中是作为一系列字符串存储的,用字符串的split函数把每个数字切割成单独的字符串
第二步:数据的转换
以上可以精简为三行代码:
file = open ('....txt','r')
S = file.read().split()
P = list(int(i) for i in S)
例子2
方法一:
f=open('唐诗一百首.txt', encoding='gbk')
txt=[]
for line in f:
txt.append(line.strip())
print(txt)
line.strip() 去除首尾空格
encoding 编码格式 utf-8,gbk
方法二:
f=open('唐诗一百首.txt')
line = f.readline().strip() #读取第一行
txt=[]
txt.append(line)
while line: # 直到读取完文件
line = f.readline().strip() # 读取一行文件,包括换行符
txt.append(line)
f.close() # 关闭文件
print(txt)
将dict对象写入json文件
import json
dictObj = {
'andy':{
'age': 23,
'city': 'shanghai',
'skill': 'python'
},
'william': {
'age': 33,
'city': 'hangzhou',
'skill': 'js'
}
}
jsObj = json.dumps(dictObj)
fileObject = open('jsonFile.json', 'w')
fileObject.write(jsObj)
fileObject.close()
读取json文件
with open('data.json', 'r') as f:
data = json.load(f)
写入json文件
with open('data.json', 'w') as f:
json.dump(data, f)
读取txt内容为列表
file_path = 'C:/...'
fi=open(file_path,'r')
txt=fi.readlines()
a=[]
for w in txt:
w=w.replace('\n','')
a.append(w)
print(a)
删除两个列表相同的元素(一对一删除)
c=[10,20,20,20,20,100,30,50,50,50]
d=[20,20,30,40,50]
for i in range(len(c)):
for j in c:
if j in d:
c.remove(j)
d.remove(j)
print(c)
print(d)
#[10, 20, 20, 100, 50, 50]
#[40]
删除字典元素
- Python字典的clear()方法(删除字典内所有元素)
#!/usr/bin/python
# -*- coding: UTF-8 -*-
dict = {'name': '我的博客地址', 'number': 10000, 'url':'http://blog.****.net'}
dict.clear(); # 清空词典所有条目
- Python字典的pop()方法(删除字典给定键 key 所对应的值,返回值为被删除的值)
#!/usr/bin/python
# -*- coding: UTF-8 -*-
site= {'name': '我的博客地址', 'number': 10000, 'url':'http://blog.****.net'}
pop_obj=site.pop('name') # 删除要删除的键值对,如{'name':'我的博客地址'}这个键值对
print pop_obj # 输出 :我的博客地址
- Python字典的popitem()方法(随机返回并删除字典中的一对键和值)
#!/usr/bin/python
# -*- coding: UTF-8 -*-
site= {'name': '我的博客地址', 'number': 10000, 'url':'http://blog.****.net'}
pop_obj=site.popitem() # 随机返回并删除一个键值对
print pop_obj # 输出结果可能是{'url','http://blog.****.net/uuihoo'}
- del 全局方法(能删单一的元素也能清空字典,清空只需一项操作)
#!/usr/bin/python
# -*- coding: UTF-8 -*-
site= {'name': '我的博客地址', 'alexa': 10000, 'url':'http://blog.****.net/uuihoo/'}
del site['name'] # 删除键是'name'的条目
del site # 清空字典所有条目
移除字典点键值(key/value)对–菜鸟教程
给定一个字典, 移除字典点键值(key/value)对。
使用 del 移除
test_dict = {"Runoob" : 1, "Google" : 2, "Taobao" : 3, "Zhihu" : 4}
# 输出原始的字典
print ("字典移除前 : " + str(test_dict))
# 使用 del 移除 Zhihu
del test_dict['Zhihu']
# 输出移除后的字典
print ("字典移除后 : " + str(test_dict))
# 移除没有的 key 会报错
#del test_dict['Baidu']
执行以上代码输出结果为:
字典移除前 : {'Runoob': 1, 'Google': 2, 'Taobao': 3, 'Zhihu': 4}
字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3}
使用 pop() 移除
test_dict = {"Runoob" : 1, "Google" : 2, "Taobao" : 3, "Zhihu" : 4}
# 输出原始的字典
print ("字典移除前 : " + str(test_dict))
# 使用 pop 移除 Zhihu
removed_value = test_dict.pop('Zhihu')
# 输出移除后的字典
print ("字典移除后 : " + str(test_dict))
print ("移除的 key 对应的 value 为 : " + str(removed_value))
print ('\r')
# 使用 pop() 移除没有的 key 不会发生异常,我们可以自定义提示信息
removed_value = test_dict.pop('Baidu', '没有该键(key)')
# 输出移除后的字典
print ("字典移除后 : " + str(test_dict))
print ("移除的值为 : " + str(removed_value))
执行以上代码输出结果为:
字典移除前 : {'Runoob': 1, 'Google': 2, 'Taobao': 3, 'Zhihu': 4}
字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3}
移除的 key 对应的 value 为 : 4
字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3}
移除的值为 : 没有该键(key)
使用 items() 移除
test_dict = {"Runoob" : 1, "Google" : 2, "Taobao" : 3, "Zhihu" : 4}
# 输出原始的字典
print ("字典移除前 : " + str(test_dict))
# 使用 pop 移除 Zhihu
new_dict = {key:val for key, val in test_dict.items() if key != 'Zhihu'}
# 输出移除后的字典
print ("字典移除后 : " + str(new_dict))
执行以上代码输出结果为:
字典移除前 : {'Runoob': 1, 'Google': 2, 'Taobao': 3, 'Zhihu': 4}
字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3}
pop和del 的差异
删除字典中的键值对的有del语句与pop方法,del 语句和 pop() 函数作用相同,pop() 函数有返回值,返回值为对应的值,del语句没有返回值。pop()函数语法:pop(key[,default]),其中key: 要删除的键值,default: 如果没有 key,返回 default 值
dic = {"张三": 24, "李四": 23, "王五" : 25, "赵六" : 27}
del dic["张三"]
print(dic)
print(dic.pop("李四"))
print(dic)
输出:
{"李四": 23, "王五" : 25, "赵六" : 27}
23
{"王五" : 25, "赵六" : 27}
2019-02-22更新:
从python3.7开始,字典按照插入顺序,实现了有序。修改一个已存在的key的值,不影响顺序,如果删了一个key后再添加该key,该key会被添加至末尾。标准json库的dump(s)/load(s)也是有序的
https://docs.python.org/3/library/stdtypes.html#dict.values
列表中元素的排列顺序不变,其中每个元素重复相同的次数
list_before = [1, 2, 3, 4, 5]
list_after = [val for val in list_before for i in range(2)]
输出:
list_after = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
展开多重嵌套的复杂数据(列表、字典等)
def data_flatten(key,val,con_s='_',basic_types=(str,int,float,bool,complex,bytes)):
"""
数据展开生成器,以键值对为最基础的数据
param key: 键,默认为基础类型数据,不做进一步分析
param val: 值,判断值的数据类型,如果为复杂类型就做进一步分析
param con_s: 拼接符,当前级的键与父级键拼接的连接符,默认为_
param basic_types: 基础数据类型元组,如果值的类型在元组之内,则可以输出
return: 键值对元组
"""
if isinstance(val, dict):
for ck,cv in val.items():
yield from data_flatten(con_s.join([key,ck]).lstrip('_'), cv)
elif isinstance(val, (list,tuple,set)):
for item in val:
yield from data_flatten(key,item)
elif isinstance(val, basic_types) or val is None:
yield str(key).lower(),val
样例数据:
test_dict = {
'a':1,
'b':2,
'c':[1,2,3,4,{'a':1,'b':2,'c':3}],
'd':{
'a':2,
'b':3,
'c':('1','2','3'),
'd':{
'a':1,
'b':['True','False']
}
},
'e':{123,3,34,'les'}
}
调用:
for i in data_flatten('',test_dict):
print(i)
输出:
将(含嵌套的)dict平铺展开
def prefix_dict(di_, prefix_s=''):
"""
把字典的每个key都带上前缀prefix_s
:param di_:
:param prefix_s:
:return:
"""
return {prefix_s + k: v for k, v in di_.items()}
def spear_dict(di_, con_s='.'):
"""
展开dict(如果下层还是dict),需要递归,展开到下层的数据类型不是字典为止
可能实用的地方:将文档类的数据格式化成更加关系化的样子可能有用
:param di_: 输入字典
:param con_s: 层级间的连接符号
:return: 深度不大于1的字典,嵌套的其他数据类型照旧
"""
ret_di = {}
for k, v in di_.items():
if type(v) is dict:
v = spear_dict(v)
# 这里或许有不写到这一层的更好写法
# for k_, v_ in v.items():
# ret_di.update({con_s.join([k, k_]): v_})
ret_di.update(prefix_dict(v, prefix_s=k + con_s))
else:
ret_di.update({k: v})
return ret_di
>>> di_
{'title': '新田商业街', 'reliability': 7, 'addressComponents': {'streetNumber': '', 'city': '深圳市', 'street': '', 'province': '广东省', 'district': '龙华区'}, 'location': {'lng': 114.09127044677734, 'lat': 22.700519561767578}, 'adInfo': {'adcode': '440309'}, 'level': 11, 'more_deep': {'loca': {'lng': 114.09127044677734, 'lat': 22.700519561767578}}}
>>> spear_dict(di_)
{'title': '新田商业街', 'reliability': 7, 'addressComponents.streetNumber': '', 'addressComponents.city': '深圳市', 'addressComponents.street': '', 'addressComponents.province': '广东省', 'addressComponents.district': '龙华区', 'location.lng': 114.09127044677734, 'location.lat': 22.700519561767578, 'adInfo.adcode': '440309', 'level': 11, 'more_deep.loca.lng': 114.09127044677734, 'more_deep.loca.lat': 22.700519561767578}
spear_dict(di_, '_')
{'title': '新田商业街', 'reliability': 7, 'addressComponents_streetNumber': '', 'addressComponents_city': '深圳市', 'addressComponents_street': '', 'addressComponents_province': '广东省', 'addressComponents_district': '龙华区', 'location_lng': 114.09127044677734, 'location_lat': 22.700519561767578, 'adInfo_adcode': '440309', 'level': 11, 'more_deep_loca.lng': 114.09127044677734, 'more_deep_loca.lat': 22.700519561767578}
嵌套列表展开
问题1:对于列表形如 list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]] 转化成列表 list_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9] 的问题。
# 普通方法
list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]]
list_2 = []
for _ in list_1:
list_2 += _
print(list_2)
# 列表推导
list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]]
list_2 = [i for k in list_1 for i in k]
print(list_2)
# 使用sum
list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]]
list_2 = sum(list_1, [])
print(list_2)
问题2:对于复杂一些的,如:list =[1,[2],[[3]],[[4,[5],6]],7,8,[9]],上面的方法就不好使了。得换个方法了,这里使用递归的方法解决。
def flat(nums):
res = []
for i in nums:
if isinstance(i, list):
res.extend(flat(i))
else:
res.append(i)
return res
实习期间学到了两种验证方式:
Token验证与用户名加密码验证
1、什么是Token验证?
Token是一种用户身份的验证方式,通常叫做令牌验证。当用户第一次登录成功后,服务器会生成一个Token并将此Token返回给用户,以后用户只需要带上这个Token前来请求数据即可,无需再用用户名和密码。
2、Token验证过程
①首次登录时,客户端通过用户名与密码请求登录
②服务端收到请求并验证用户名与密码
③若验证通过,服务端会签发一个Token,该Token会保存在服务端的数据库中,并且也会返回给客户端
④客户端收到Token并存储起来,比如放在Cookie,SessionStorage,LocalStorage。
⑤客户端每次向服务端请求资源时都会带着Token
⑥服务端收到请求,然后验证客户端请求里面带着的Token,即将客户端的Token与本地数据库中的Token作对比,如果两个Token相同,说明用户曾登录成功过,则验证通过,服务端向客户端返回请求数据。
⑦若两个Token不同,则验证不通过,需要通过用户名和密码进行登录
3、为什么使用Token验证?
当客户端多次向服务端请求数据时,服务端就需要多次从数据库中查询用户名和密码并进行比对,判断用户名和密码是否正确匹配,并作出相应提示。查询数据库是比较消耗资源的,这样无疑会增加服务器的运行压力。为了既能够验证用户登录情况又能够减轻服务器的压力,便引入了Token验证。Token一般是保存在内存中,这样的话就不用查询数据库,减少了频繁的查询数据库,使服务器更加健壮。
什么是增量表,全量表,快照表
按照每天存放的数据以及是否按天分区可以分为增量表,全量表和快照表
项目 | Value | a |
-------- | ----- ||
电脑 | $1600 ||
手机 | $12||
导管 | $1| |
全量表 | 增量表 | 快照表 | |
---|---|---|---|
数据 | 包含到前一天的全量数据 | 前一天的增量数据 | 包含到前一天的 全量数据 |
分区 | 不分区(ymd为当前日期) | 按照每一天分区 | 按照每一天分区 |
具体查看:
https://blog.****.net/Jun2613/article/details/106688930
另外full outer join