python 数据存储之HDF5

import h5py

import numpy as np

一、数据和元数据的组织:

In [12]: temperature=np.random.random(1024)

In [13]: temperature
Out[13]:
array([ 0.91976222,  0.07664957,  0.28241276, ...,  0.93644539,
        0.89382664,  0.37702447])

假设这些数据来自某个气象站十秒一次的温度采样。为了让这些数据有意义,我们还需要记录采样的时间间隔“delta-T”。以及记录第一个数据获取的时间起点,以及这些数据来自8号气象站:

dt         = 10.0
start_time = 1533971134
station    = 8

我们可以用一个简单的Numpy内建函数np.savez来将这些数据存入磁盘:

np.savez("weather.npz",data=temperature,start_time=start_time,station=station)

我们可以用 np.load 从文件中获取这些数据:

In [18]: out = np.load("weather.npz")

In [19]: out['data']
Out[19]:
array([ 0.91976222,  0.07664957,  0.28241276, ...,  0.93644539,
        0.89382664,  0.37702447])

In [20]: out['start_time']
Out[20]: array(1533971134)

In [21]: out['station']
Out[21]: array(8)

如果我们的气象站数据不止一组怎么办,比如还要一组风速数据:

In [23]: wind = np.random.random(2048)

In [24]: dt_wind = 5.0

在假设我们不止一个气象站。也许我们可以引入某种命名规范,比如“wind_8”作为8号气象站的风速数据,“dt_wind_8”作为采样时间间隔。那么或许我们需要使用多个文件去完成。

现在我们使用 HDF5 来存储试试:

In [25]: f = h5py.File('weather.hdf5')

In [26]: f['/8/temperature'] = temperature

In [27]: f['/8/temperature'].attrs['dt'] = 10.0

In [28]: f['/8/temperature'].attrs['start_time'] = 1533971134

In [29]: f['/8/wind'] = wind

In [30]: f['/8/wind'].attrs['dt'] = 5.0

......

In [31]: f['/9/temperature'] = temperature_9

取出:

In [40]: dataset = f['/8/temperature']

In [41]: dataset[:10]
Out[41]:
array([ 0.91976222,  0.07664957,  0.28241276,  0.68921452,  0.59650297,
        0.50639705,  0.87994178,  0.07439151,  0.40971268,  0.81227045])

In [42]: dataset.value
Out[42]:
array([ 0.91976222,  0.07664957,  0.28241276, ...,  0.93644539,
        0.89382664,  0.37702447])

In [43]: for key,value in dataset.attrs.items():
    ...:     print(f'{key}:{value}')
    ...:
dt:10.0
start_time:1533971134

HDF5数据模型的三大要素:

数据集:一种数组型对象,在磁盘上保存数值类型的数据;

组:层次性容器,可以包含数据集和子组;

特征:自定义元数据信息,可被附加在数据集以及组上。

查看 key:

In [49]: list(f.keys())
Out[49]: ['8']

In [50]: list(f['/8'].keys())
Out[50]: ['temperature', 'wind']

二、开始使用 HDF5

f = h5py.File('name.hdf5', 'w')  # 写
f = h5py.File('name.hdf5', 'r')  # 读
f = h5py.File('name.hdf5', 'r+') # 读写
f = h5py.File('name.hdf5', 'a')  # 追加

f = h5py.File('name.hdf5', 'w-')  # 写,如果存在此文件,则会报错,避免了覆盖原文件

f.close()  # 别忘了保存后关闭文件

__文件驱动

文件驱动处于文件系统和 HDF5 高级抽象(组、数据集和特征)之间。一般情况下是无需设置的,因为默认的驱动适用于大部分应用程序。

1、core 驱动:

core 驱动会将你的文件保存在内存中,它对于能够存储的数据量显然是有限的,但是优点是超快速读写。

f = h5py.File('name.hdf5',driver='core')

# 还可以在要求 HDF5 在磁盘上创建一个 “备份存储” 文件,
# 当内容中的文件映象被关闭时,其内容会被保存到磁盘上。
f = h5py.File('name.hdf5',driver='core',backing_store=True)

2、mpio 驱动:

并发 HDF5 的核心,它允许多个同时运行的进程访问同一个文件。你可以同时有成百上千个并发计算的进程,他们在共享访问磁盘上同一个文件时能保证数据的一致性。将在以后会介绍到。

——用户块:

f = h5py.File('name.hdf5','w',userblock_size=512)
f.close()
with open('name.hdf5', 'r+') as f:
    f.write('a'*512)

三、使用数据集:

创建空数据集:

In [93]: dset = f.create_dataset('test1',(10,10))

In [94]: dset
Out[94]: <HDF5 dataset "test1": shape (10, 10), type "<f4">

In [95]: dset = f.create_dataset('test2',(10,10),dtype=np.complex64)

In [96]: dset
Out[96]: <HDF5 dataset "test2": shape (10, 10), type "<c8">

四、HDF5 并发:多线程:

由于 GIL,一个基于线程的python程序只能一次使用一个处理器的时间。所以在HDF5上使用多线程,在效率上并没有多大提升

import threading
import time
import random
import numpy as np
import h5py



class ComputeThread(threading.Thread):

	def __init__(self,axis):
		self.axis = axis
		threading.Thread.__init__(self)

	def run(self):
		for idx in range(1024):
			random_number = random.random()*0.01
			time.sleep(random_number)
			with lock:
				dset[self.axis,idx] = random_number

if __name__ == '__main__':
	f = h5py.File('thread.hdf5','w')
	dset = f.create_dataset('data',(2,1024),dtype='f')
	lock = threading.RLock()

	thread1 = ComputeThread(0)
	thread2 = ComputeThread(1)

	thread1.start()
	thread2.start()

猜你喜欢

转载自blog.csdn.net/a649344475/article/details/81586825
今日推荐