Python-玩转数据-I/O操作小结

一、说明

在大量数据的今天,存储的数据量的增长已经远远超过了随机存储内存(RAM)的能力,通常处理的数据不超过GB的大小,对Python以及其科学计算库,例如NumPy, pandas和PyTables来说是很合适的。这样规模的数据集合也可以在内存中进行分析(归因于目前比较快的CPU和GPU),但是即使是在内存中处理,也需要将数据从磁盘上读入,结果再写回磁盘,这都是需要I/O操作的。

二、将对象写入磁盘

1、pickle模块

pickle提供了一个简单的持久化功能。可以将对象以文件的形式存放在磁盘上。pickle模块只能在python中使用,python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化,pickle序列化后的数据,人一般无法识别。pickle模块对于错误或恶意构造的数据是不安全的。

import pickle

if __name__=='__main__':
    path='test1'
    f = open('test1','wb')
    data = {'a':123,'b':234,'c':[[1,2],[4,5]]}
    #序列化
    pickle.dump(data,f)
    f.close()

    f1 = open('test1','rb')
    #反序列化
    data1 = pickle.load(f1)
    print(data1)
    f1.close()

三、读写文本文件

1、python读写txt

Python的文本文件的内容读取中,有三类方法:read()、readline()、readlines(),这三种方法各有利弊。

read()一次性读取文件的所有内容,放在一个大字符串中,即存在内存中,优点是方便、简单,一次性独读出文件放在一个大字符串中,速度最快。弊端是文件过大的时候,占用内存会过大。

readline()逐行读取文本,结果是一个list,readline()的优点是占用内存小,逐行读取。readline()的弊端是由于是逐行读取,速度比较慢

readlines()一次性读取文本的所有内容,结果是一个list,优点是一次性读取文本内容,速度比较快,弊端是随着文本的增大,占用内存会越来越多,最简单、最快速的逐行处理文本的方法:直接for循环文件对象。

truncate()表示清空文件
write()写入文本
seek(3)定位到第4个元素前,0表示文件开始,也就是第1个元素前。
seek(3, 1)第二个参数默认是0,表示从文件开始处读取;1表示从当前位置开始计数;2表示从文件最后开始。
read(1)读取一个字节,指针会根据读取的大小移动相应的位置。
tell()取得当前指针的位置。

f = open('test1.txt','w')
data = "{'a':123,'b':234,'c':[[1,2],[4,5]]}\n"
f.truncate()
for i in range(5):
	#写入
    f.write(data)
f.close()

f1 = open('test1.txt','r')
#读取
print(f1.read())
#定位到第二十个字符
f1.seek(20)
print(f1.read())
f1.close()

2、python读写csv文件

一定要注意,csv文件在写入时,字段和字段之间是用逗号“”,“”分割的,如果稍微不注意,就会出现串行的情况,with语句打开文件,循环结束后自动关闭。

import csv
#加入newline='',换行后不会空行
with  open('test.csv', 'w',newline ='') as csvFile:
    data = ['a',123,'b',234,'c',[[1, 2],[4, 5]]]
    writer = csv.writer(csvFile)
    # 先写columns_name
    writer.writerow(data)
    # 写入多行用writerows
    writer.writerows([[1, 2, 3],[0, 1, 2],[4, 5, 6]])

# 用reder读取csv文件
with open('test.csv', 'r') as csvFile:
    reader = csv.reader(csvFile)
    for line in reader:
        print(line)

3、python读写excel文件

import xlwt

#创建工作簿
f = xlwt.Workbook()
#创建sheet
sheet1 = f.add_sheet(u'sheet1',cell_overwrite_ok=True)
row0 = [u'编号',u'单位',u'网站备案号',u'域名',u'外链名称',u'不良网站名',u'不良url地址',u'地市',u'ip地址',u'截图',u'备注',u'审核时间',u'父链接',u'源码超链接']
#生成第一行
for i in range(0,len(row0)):
     sheet1.write(0,i,row0[i])  # 顺序为x行x列写入第x个元素
f.save('newfile.xls')


import xlrd
data = xlrd.open_workbook('newfile.xls') # 打开xls文件
table = data.sheets()[0] # 打开第一张表
nrows = table.nrows      # 获取表的行数
for i in range(nrows):   # 循环逐行打印
    # if i == 0: # 跳过第一行
    #     continue
    print (table.row_values(i))

四、SQL数据库

Python与几乎所有的数据库都较好的进行了结合,基本的SQL语法是由使用的数据库来决定的。Python可以与SQL数据库配合使用,而且对于一般的NoSQL数据库也是支持的。与Python默认安装的一个数据库是SQLite3,SQLite是一款轻型的数据库。

我们使用这个数据库来描述Python处理SQL数据库的一般方法,支持数据库大小至2TB。

import sqlite3 as sq

#第一步:连接数据库(如果数据库不存在就会创建新的数据库)
# 可以指定创建数据库的路径,sq.connect(r"E:\DEMO.db")
con = sq.connect("DEMO.db")
#第二步:创建游标#
cur = con.cursor()
#第三步:(一) 创建表
sql = "CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY,name TEXT,age INTEGER)"
cur.execute(sql)

# 添加单条数据
data = "1,'Desire',5"
cur.execute('INSERT INTO test VALUES (%s)' % data)
# 添加单条数据
cur.execute("INSERT INTO test values(?,?,?)", (6, "zgq", 20))
# 添加多条数据
cur.executemany('INSERT INTO test VALUES (?,?,?)', [(3, 'name3', 19), (4, 'name4', 26)])

# 修改数据方式一
cur.execute("UPDATE test SET name=? WHERE id=?", ("nihao", 1))
# 修改数据方式二
cur.execute("UPDATE test SET name='haha' WHERE id=3")

# 删除数据方式一
cur.execute("DELETE FROM test WHERE id=?", (1,))
# 删除数据方式二
cur.execute("DELETE FROM test WHERE id=3")

#1、查询所有数据
cur.execute("select * from Test")
print(cur.fetchall())

#2、查询第一条数据
cur.execute("select * from Test")
print(cur.fetchone())

#3、查询多条数据
print(cur.fetchmany(3))

#事务的提交
con.commit()
#事务回滚
con.rollback()
#断开会话连接,释放资源
# 关闭游标
cur.close()
# 断开数据库连接
con.close()
#创建一个无类型的表(创建表的SQL语句字段不加类型即可)#

sql = "CREATE TABLE IF NOT EXISTS user(clo_1,clo_2,clo_3)"
cur.execute(sql)
#添加数据的时候就可以添加任意类型的数据(没有限制)#

sql = 'INSERT INTO user VALUES (?,?,?)'
data = [(9, 'name3', 19), ('name4', 26, "nihao"), ('nihao', 3, 2.89)]
cur.executemany(sql, data)
con.commit()

五、pandas读写数据

常见的excel文件(后缀名为xls和xlsx),csv、txt等文本文件,json文件以及sql文件等等。pandas读取这些数据文件的方法如表格所示:
在这里插入图片描述

1、pandas 的csv读写

import pandas

# csv文件读取
with open('a.csv','w') as csv:
    csv = pandas.read_csv("wbdata.csv",encoding="gbk",header=0,delimiter=",")
    print(csv)
    #将读到的csv信息存储到a.csv文本文件
    csv.to_csv("a.csv",sep=",",header=['内容','热度'],columns=['内容','热度'],index_label="序号",encoding='gbk')

2、pandas 的excel读写

import pandas
# 读取Excel
with open('员工信息表.xlsx','r') as xel:
    xel = pandas.read_excel("员工信息表.xlsx")
    print(xel)
    # 写入excel
    y = xel.to_excel('b.xlsx',sheet_name='Sheey1',na_rep='--',header=['姓名', '年龄'],columns=['姓名','年龄'],index=False)

3、pandas 的mysql读写

# 连接数据库
import pandas
import pymysql
conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password="123456",db="test",charset="utf8")
sql = "select * from test"
df = pandas.read_sql(sql,conn)
print(df)
conn.close()
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test')
# engine = create_engine('mysql+pymysql://root:123456@localhost:3306/test')
sql = "DROP TABLE IF EXISTS test_input"
cursor = conn.cursor()
cursor.execute(sql)

六、读写NumPy数组

1、 数组以二进制格式保存

np.save和np.load是读写磁盘数组数据的两个主要函数。默认情况下,数组以未压缩的原始二进制格式保存在扩展名为npy的文件中,以数组a为例

np.save("filename.npy",a)
b = np.load("filename.npy")

利用这种方法,保存文件的后缀名字一定会被置为.npy

2、 存取文本文件

使用 np.savetxt 和 np.loadtxt 只能读写 1 维和 2 维的数组
np.savetxt:将数组写入以某种分隔符隔开的文本文件中
np.loadtxt:指定某种分隔符,将文本文件读入到数组中

np.savetxt("filename.txt",a)
b =  numpy.loadtxt("filename.txt", delimiter=',')

3、 保存为二进制文件

使用数组的 tofile 函数可以方便地将数组中数据以二进制的格式写进文件

a.tofile("filename.bin")
b = np.fromfile("filename.bin",dtype = **)

该方法与np.save有几点区别:

tofile函数只能将数组保存为二进制文件,文件后缀名没有固定要求。这种保存方法对数据读取有要求,np.fromfile 需要手动指定读出来的数据的的dtype,如果指定的格式与保存时的不一致,则读出来的就是错误的数据。
tofile函数不能保存当前数据的行列信息,不管数组的排列顺序是C语言格式的还是Fortran语言格式,统一使用C语言格式输出。因此使用 np.fromfile 读出来的数据是一维数组,需要利用reshape指定行列信息。
例如下面的例子所示:

>>> a = np.arange(0,12)
>>> a.shape = 3,4
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a.tofile("a.bin")
>>> b = np.fromfile("a.bin", dtype=np.float) # 按照float类型读入数据
>>> b # 读入的数据是错误的
array([  2.12199579e-314,   6.36598737e-314,   1.06099790e-313,
         1.48539705e-313,   1.90979621e-313,   2.33419537e-313])
>>> a.dtype # 查看a的dtype
dtype('int32')
>>> b = np.fromfile("a.bin", dtype=np.int32) # 按照int32类型读入数据
>>> b # 数据是一维的
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> b.shape = 3, 4 # 按照a的shape修改b的shape
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

七、python之pytable读写hdf5格式文件

从tables的读,写,以及一些简单的操作进行简要描述。使得tables这个tool能够为我们所用。

首先,我们先介绍下HDF5(Hierarchical Data Format).HDF 是用于存储和分发科学数据的一种自我描述、多对象文件格式。HDF 是由美国国家超级计算应用中心(NCSA)创建的,以满足不同群体的科学家在不同工程项目领域之需要。HDF 可以表示出科学数据存储和分布的许多必要条件。

HDF文件是安装树状结构组织起来的。其顶部是根节点(),根节点下可以接很多分组(group),每个分组下有可以有很多节点,包括表(table),数组(array),压缩数组(compression array,Earray),可扩展压缩数组(enlargeable array,Earray),变长数组(variable length array,VLarray)。每个节点下还有叶子节点,即最终存储的数据。

简单知道HDF5文件的特征,我们接着介绍下,在python下如何使用tables(其实还有H5Py这个包也是可以用)这个package来实现对HDF5文件的操作。 Python 中有一系列的工具可以操作和使用 HDF5 数据,其中最常用的是h5py和PyTables。
假设大家已经把tables及其依赖的库如numpy等包安装好在python的环境下。

1 、写数据到表

这里简单以pytable里面的例子进行说明。对于table,我们首先要定义表格中每个元素(field)的数据类型,长度等信息。如下图,我们定义了一个particle类,其名称,数据类型,及长度。比如说name这个field是字符串类型,最大长度是16个字节。

from tables import *

class particle(IsDescription):

'''definition '''

name = StringCol(16) #16-character string

_id = Int64Col() #signed 64-bit interger

energy = Float64Col() #double-precision

新建一个hdf5文件,文件名是tutorial.h5, 写的模式,描述为test file。

f = open_file('tutorial.h5',mode='w',title='test file')

为了更好地组织数据,我们在根节点下新建一个分组叫detector,描述为Detector information。

group = f.create_group('/','detector','Detector information')

“/”可以由f.root代替。
接着,我们在detector这个分组下建立一个新的表(table)叫做‘readout’,并初始化为particle形式。

table=f.create_table(group,'readout',particle,'Readout_example')

接着,我们往表里添加数据。其中append这个函数用于把数据写入到I/O buffer中。

for i in range(10):

particle['name']='particle: %6d' %(i)

particle['_id'] = i *(2 **34)

particle['energy'] = float(i *i)

particle.append()

table.flush()

最后还需要调用flush函数把数据写入到硬盘中,并且会释放被占用的内存,这样我们就可以处理海量的数据,而不用担心内存不足。

2、 从表中读数据

我们把数据存到硬盘里面,接下的步骤要从硬盘把数据读出来。我们首先定位到表。接着我们还可以查询我们感兴趣的数据。我们的查询是通过 Table.iterrows() 这个迭代器,它把表中的每行提取出来。

table = f.root.detector.readout

energy = []

for x in table.iterrows():

energy.append(x)

3、 创建数组对象(Array object)

把数据放在table是数据组织很好的方式,但是当我们的数据并没有那么复杂,并没有包含很多属性,我们可以简单地使用数组来组织数据。比如我们想存储矩阵数据,

features = np.random.rand(100,100000)

f = tables.openFile('feat.h5','w')

f.createArray(f.root,'feature',features)

f.close()

4、 压缩数组(Compression Array)

HDF文件还可以进行压缩存储,压缩方式有blosc, zlib, 和 lzo。Zlib和lzo压缩方式需要另外的包,blosc在tables是自带的。我们需要定义一个filter来说明压缩方式及压缩深度。另外,我们使用creatCArray来创建压缩矩阵。

f = tables.open_file('feat.h5', mode='w')

features = np.random.rand(100,100000)

filters=Filters(complevel=5,complib='blosc')

data_storage = f.createCArray(f.root,'feature',

Atom.from_dtype(features.dtype),

shape=features.shape,filters=filters)

data_storage[:]= features

f.close()

5、 压缩可扩展数组(Compression & Enlargeable Array)

压缩数组,初始化之后就不能改变大小,但现实很多时候,我们只知道维度,并不知道我们数据的长度。这个时候,我们需要这个数组是可以扩展的。HDF文件也提供这样的接口,我们能够扩展其一个维度。同CArray一样,我们也先要定filter来声明压缩类型及深度。最重要的是,我们把可以扩展这个维度的shape设置为0。扩展数据的时候就使用append,这个数据shape必须为(1,data.shape[1])

f = tables.open_file('feat.h5', mode='w')

features = np.random.rand(100,100000)

filters=Filters(complevel=5,complib='blosc')

data_storage = f.createEArray(f.root,'feature',

Atom.from_dtype(features.dtype),

shape=(0,features.shape[1]),filters=filters)

for x in range(features.shape[0]):

data_storage.append(features[:,x])

f.close()

上述我们存储的数据是浮点型,当我们要存储字符串类型的,我们同样定义:

image_name = '123fjo.jpg'

imageName_storage = f.createEArray(f.root,'filename',tables.StringAtom(itemsize=32),shape=(0,))

image_name = np.array([image_name],dtype=np.object)

imageName_storage.append(image_name)

如果我们不知道字符串的字节数,我们在初始化的时候就不需要填。接着,我们需要把python string类型转换为numpy object类型。这样在添加数据就没有问题了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值