json:
json异于pickle,无乱码,各语言都支持,但Python各对象只直接接收int,str,(),[],{}。读入txt时只接受str,int变为str(int),()[]{}被json.dumps(*)换装为str后才行;反义词json.loads(json风格的str)返回()[]{}。
json虽是str类型,却有其独特风格,即引号只用双引号:因为有的编程语言如VBA并没用'而只用",故而通行各门语言的json也只用双引号。
import json
html1="{'a':1,'b':2,'中':3,'外':'国'}"
print(json.loads(html1)) #×
html2='{"a":1,"b":2,"中":3,"外":"国"}'
print(json.loads(html2))
******分割线******
import json
pythonType={'a':1,'b':2,'中':3,'外':'国'}
strStyle=str(pythonType)
print(type(strStyle),strStyle) #无意义的单引号str:{'a': 1, 'b': 2, '中': 3, '外': '国'}
#中文不要转为u节码,各键值对换行显示,去除空格分隔符
jsonStyle=json.dumps(pythonType,ensure_ascii=False,indent='').replace(": ",":")
print(type(jsonStyle),jsonStyle) #双引号str:{"a":1,"b":2,"中":3,"外":"国"}
with open('E:/temp.txt','a+',encoding='utf8') as f: #写入或读取txt
f.write(jsonStyle) #非str类型如()[]{},转为json风格的str后才能写入txt;int则str(int)
f.seek(0) #.write(*)或.read()后,指针移到了文件尾,回到开头以正常使用该文件
txt=f.read()
print(type(txt),txt)
pythonType=json.loads(txt)
print(type(pythonType),pythonType)
**********************分割线**********************
key没套""的json字串:
import execjs
jsonStyle='{a:"111",b:22,c:3}'
pythonType=execjs.eval(jsonStyle)
**********************分割线**********************
让类对象貌似也能被json读入读出:
import json
class Student:
def __init__(self,name,age,score):
self.name=name
self.age=age
self.score=score
def test(self):
print(self.name,'good morning~')
s=Student('Bob',20,88)
# s.favorite='Python' #实例的私有属性可装入文件,但读回时无法和类挂钩,故不用
f=open('早上好.txt','r+')
json.dump(s.__dict__,f) #装入实例s的属性——1个字典到文件
# json.dump(s,f,default=lambda instance:instance.__dict__) #改装实例s为json能接收的{}
f.seek(0) #dump()和read()一样,用过之后指针都到了文末
w=json.load(f,object_hook=lambda d:Student(**d)) #文件内容做lambda的实参,返回新实例
f.close()
print(w.__dict__)
w.test()
****************************************分割线****************************************
csv:
Egのutf8编码的字串写入csv文件,并能用Excel正常打开:
import codecs,csv
with open('test.csv','ab') as f:
f.write(codecs.BOM_UTF8)
with open('test.csv','a',encoding='utf8') as f:
wr=csv.writer(f)
wr.writerow(['影片名','评分','概况','年份','类别'])
**********************分割线**********************
Egの读取csv文件的俩常用库——csv和pandas:
import csv,pandas as pd,requests
from io import StringIO
df=csv.DictReader(open('E:/students.csv')) #文件;若with … as f,则用f.readlines()
for row in df: #row是collections.OrderedDict对象
print(df.fieldnames,row['姓名'],row.keys(),row.values(),sep='\n')
break
df=pd.read_csv('E:/students.csv',encoding='gbk') #文件路径字串,无需open
for row in df.iterrows(): #row是元组:(序号,pandas.Series对象)
print(row[1][0],row[1]['姓名'],row[1].index,row[1].values,sep='\n')
break
url='http://pythonscraping.com/files/MontyPythonAlbums.csv' #不下载直接读自网络
file=StringIO(requests.get(url).text)
df=csv.reader(file)
headers=next(df)
for row in df:
print(row)
****************************************分割线****************************************
txt:
open打开文件的几种mode:
文件无则报错:r读,r+读后再f.seek(0)可覆盖写;
文件无则新建:a+末尾写并在f.seek(0)后可读,a末尾写;w清空写,w+清空写后再f.seek(0)可读。
a*或w*模式所新建的文本,纯英文编码会坚持utf8,写入有中文才能让指定的gbk生效。
相较直接open,变身为【with open(filepath) as f】的优点:with可自动open和close文件;而且把文件对象f当做迭代对象,将自动处理IO缓冲和内存管理,无需担心几个G的大文件的处理。
**********************分割线**********************
Egの各txt的编码不详,统一转换为gbk:若特殊字符出没于ANSI而非utf8文件,则utf8和gbk都不能解码,只能抛弃这1行。
import pandas as pd,os
from tkinter.filedialog import askopenfilenames as ofn
from gevent import monkey;monkey.patch_all()
from gevent.pool import Pool
#法1のpandas读写一条龙:不过utf8和gbk都不能解码的那些行,只能换用法2弃之
def changeCoding1(coding,file):
newfile=file[::-1].replace('.','.)wen(',1)[::-1]
with open(file) as f: #未.read()的open对象,可让pandas间接支持中文路径
try:
df=pd.read_table(f,skip_blank_lines=False,encoding='utf8')
except:
f.seek(0) #pd.read_table(f),相当于f用指定或默认编码作.read()
df=pd.read_table(f,skip_blank_lines=False,encoding='gbk')
df.to_csv(newfile,index=False,encoding=coding)
#法2の边读边写:open1读为二进制+逗号语法+逐行解码并去干扰后给open2抄写
def changeCoding2(coding,file):
newfile=file[::-1].replace('.','.)wen(',1)[::-1]
with open(file,'rb') as r,open(newfile,'w',encoding=coding) as w:
for index,line in enumerate(r): #各行及\n的list,用[i]则补全.readlines()
try:w.write(line.decode('utf8').rstrip()+'\n') #*b模式打开,行尾会多个\r\r
except:
try:w.write(line.decode('gbk').rstrip()+'\n')
except:print(f'{file}的第{index+1}行解码失败')
def main(func):
coding='gbk'
files=ofn(initialdir=os.path.dirname(__file__),title='请选择要转换编码的各文本')
p=Pool(size=4)
[p.spawn(func,coding,file) for file in files]
p.join()
if __name__ == '__main__':
main(changeCoding2)
**********************分割线**********************
Egの遍历目录下的文本或excel,把证件的8位生日、手机的4位城市,都改为*:
import os,re,pandas as pd
def handleText(file):
try:
f=open(file,'r+')
text=f.read()
except:
f=open(file,'r+',encoding='utf8')
text=f.read()
text=re.sub('(\d{6})\d{8}',r'\1'+'*'*8,text)
text=re.sub('(\d{3})\d{4}',r'\1'+'*'*4,text)
f.seek(0)
f.write(text)
f.close()
def handleExcel(file):
df=pd.read_excel(open(file,'rb'),skip_blank_lines=False)
df.replace('(\d{6})\d{8}',r'\1'+'*'*8,inplace=True,regex=True)
df.replace('(\d{3})\d{4}',r'\1'+'*'*4,regex=True).to_excel(file,index=False)
def main(folderPath):
allfiles=[]
for folder,useless,files in os.walk(folderPath):
allfiles.extend([os.path.join(folder,file) for file in files])
for file in allfiles:
suffix=os.path.splitext(file)[-1][1:]
if suffix in ['txt','csv','py','md']:
handleText(file)
elif suffix in ['xls','xlsx']:
handleExcel(file)
if __name__ == '__main__':
folderPath='D:\待遍历文件夹'
main(folderPath)
****************************************分割线****************************************
xlsx:
Egの新建及打开xlsx文件:
from openpyxl import Workbook #新建工作簿
wb = Workbook()
ws = wb.active
ws.title='豆'
ws.append(['书名', '评分', '作者', '网址'])
ws.append(['龙符', '9.9', '梦入神机', 'http://book.zongheng.com/book/523438.html'])
wb.save('E:\豆瓣.xlsx')
from openpyxl import load_workbook #打开已存在的工作簿
from openpyxl.styles import Font
wb=load_workbook('E:\豆瓣.xlsx')
ws=wb.worksheets[0] #获取第1张表;②通过表名获取:wb['豆']
print(ws.max_row)
ws['A1'].font=Font(name='微软雅黑', size=12) #ws['A1'].number_format='@'
wb.save('E:\豆瓣.xlsx')