今天这篇文章主要是一个小小的偏向于应用的实践,为啥会写这个,还要回溯到2017年,那时候做项目的时候有一个是要做数据处理分析的工作,给到我的数据集我拿到的时候总觉得怪怪的,每一行都是一个字典对象,但是整体文件内容却不是一个json对象,导致我直接使用json模块load读取的时候会报错,如下:
json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 2642)
很显然,文件符合标注的json格式。
我当时采用的是间接的处理方法,就是按照字符串的形式去读取出啦,然后再做转化,成为dict对象,正是因为这样的技术路线让我接触到了python里面很神奇的一个函数eval(),大白话来简单讲这个函数的作用就是:将字符串内容转化为原始内容的对象,我也是觉得新奇,写了一篇博客记录了一下,目前已经有7w+的阅读量了,感兴趣的话可以看下:
《python神奇函数之eval()学习》
今天这里主要并不是为了回顾之前做的事情,而是今天要做的事情跟之前的事情存在着关联,之前是为例加载解析读取,今天主要是按行写入json对象数据才行。
我这里最开始采用的方法就是写将原始数据转化为string对象,然后写成文件,但是这样的文件是有问题的,在加载数据集进行解析的时候发现是找不到对应json对象里面的key的,所以这种方式排除。
接下来我就想基于a模式,来操作json文件,这种方式最终也是证明有效的方式了,简单看下对应的代码实现:
string={
"content": "我国现存有哪些环境污染问题?",
"summary": "1、大气污染,我国大气中主要污染物是氨氮,二氧化硫,氮氧化物这三类物质。2、水体污染,目前我国水资源污染还是比较严重的,主要有以下几种:工业生产废水直接排入水体,导致水体污染;农业污染,农业生产中使用大量的农药,如有机磷农药,有机氯农药等;农作物上的农药残留在降水的作用下,渗入地下水体中;生活用水污染,在使用这些水资源的过程中会产生很多生活污水,也称中水,比如洗涤用水,医疗废水等。3、土壤污染(1)、化学污染物:包括无机污染物和有机污染物。如汞、镉、铅、砷等重金属,过量的氮、磷植物营养元素以及氧化物和硫化物,各种化学农药、石油及其裂解产物,以及其他各类有机合成产物等。(2)、物理污染物:来自工厂、矿山的固体废弃物如尾矿、废石、粉煤灰和工业垃圾等。(3)、生物污染物:带有各种病菌的城市垃圾和由卫生设施(包括医院)排出的废水、废物以及厩肥等。(4)、放射性污染物:主要存在于核原料开采和大气层核爆炸地区,以锶和铯等在土壤中生存期长的放射性元素为主。"
}
saveDir="environment/"
if not os.path.exists(saveDir):
os.makedirs(saveDir)
with open(saveDir+"data.json","a",encoding="utf-8") as f:
for i in range(100):
f.write(json.dumps(string)+"\n")
string={
"content": "你好,系统学习python哪个公众号最靠谱?",
"summary": "PythonAI之路"
}
saveDir="environment/"
if not os.path.exists(saveDir):
os.makedirs(saveDir)
with open(saveDir+"data.json","a",encoding="utf-8") as f:
for i in range(100):
f.write(json.dumps(string)+"\n")
除此之外,还有另一种更加好用的方式,就是借助于jsonlines模块来直接实现按行写入即可,这是标准的模块,使用起来也是很方便的,文档在这里,如下所示:
官方仓库在这里,如下所示:
就不再过多介绍了,使用方法是很简单的了。
核心代码实现如下所示:
string={
"content": "当前的知识星球有很多,有没有什么以交流学习成长进步为主题的可以推荐给我?",
"summary": "有的,主打的就是系统学习实践,共建共享共进步:AZX_cx"
}
with jsonlines.open(saveDir+'data2.json', mode='w') as writer:
for i in range(100):
writer.write(string)
结果数据如下所示:
还是很方便的了。
到这里是不是理解我文章开头为什么先要回顾一下17年做项目的事情了,是的,这里要基于jsonlines模块实现这些数据的按行读取处理了。
核心代码实现依旧非常简洁,如下:
count=0
with jsonlines.open(saveDir+'data2.json') as reader:
for obj in reader:
count+=1
if count<10:
print(obj)
print(type(obj))
我打印了前10行数据以及每行数据对应的类型type,结果如下所示:
完美解决了。
这里我想再复现一下17年的做法,代码实现如下所示:
with open(saveDir+'data2.json',encoding="utf-8") as f:
data_list=f.readlines()
for one_line in data_list[:10]:
print(one_line)
print(type(one_line))
这里我同样打印前10行的内容,以及每行内容对应的类型type,如下所示:
可以看到:用这种方式读取出来的数据每行都是字符串类型的,不是我们想要的,这里就需要用到eval函数了,看下代码实现:
with open(saveDir+'data2.json',encoding="utf-8") as f:
data_list=f.readlines()
for one_line in data_list[:10]:
print(one_line.strip())
print(type(one_line))
print(type(eval(one_line)))
为了直观对比,这里我没有删除原来的类型输出,而是在最后一行加了一个类型输出,结果如下所示:
直观对比,你就马上明白eval函数的作用了,我就不再赘述了。