关于 h5py
h5py 是连接 NumPy 与 HDF5 的 Python 库,用于组织和访问大型数值数据集。它适合需要分层存储、元数据及按需读取磁盘数据的科学与数据处理工作。
主要功能
- 01分层管理组与数据集
- 02支持 NumPy 式切片
- 03为对象附加元数据属性
- 04分块与压缩存储
- 05创建可调整大小的数据集
适用场景
- 01存储大于可用内存的数组
- 02组织科学数据及其元数据
- 03读取大型文件中的选定区域
- 04随时间追加模拟数据
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tondevrel/ scientific-agent-skills --skill h5py安装后在 Claude Code 中输入/h5py确认已加载。
详细介绍
h5py - 分层数据存储
h5py 在 NumPy 与 HDF5 之间提供了无缝桥接。它允许你将数据组织到组(类似文件夹)和数据集(类似 NumPy 数组)中,并为每个对象附加丰富的元数据(属性)。
适用场景
- 存储远大于计算机 RAM 的数据集。
- 将复杂的科学数据组织成分层的“文件夹式”结构。
- 存储支持高速随机访问的数值数组(NumPy)。
- 将元数据(单位、实验日期、参数)直接附加到数据上。
- 在不同语言(C、C++、Fortran、Java、MATLAB)之间共享数据,因为 HDF5 是跨平台标准。
- 分块读取/写入大型数据集,以优化 I/O 性能。
参考文档
官方文档:https://docs.h5py.org/
HDF Group:https://www.hdfgroup.org/
搜索模式:h5py.File、create_dataset、h5py.Group、chunks=True、compression="gzip"
核心原则
层级结构
HDF5 文件包含两种主要对象:
- 数据集:多维数据数组(类似 NumPy)。
- 组:可以容纳数据集或其他组的容器结构(类似目录)。
切片
h5py 数据集支持标准的 NumPy 切片。对数据集进行切片时,只会从磁盘读取指定切片,从而减少内存占用。
属性
每个组和数据集都可以包含用于存储元数据的属性(键值对)。
快速参考
安装
pip install h5py
标准导入
import h5py
import numpy as np
基本模式 - 写入和读取
import h5py
import numpy as np
# Writing data
with h5py.File('data.h5', 'w') as f:
dset = f.create_dataset('main_data', data=np.random.rand(100, 100))
dset.attrs['units'] = 'meters'
grp = f.create_group('subgroup')
grp.create_dataset('results', data=[1, 2, 3])
# Reading data
with h5py.File('data.h5', 'r') as f:
data_slice = f['main_data'][0:10, 0:10] # Only read 100 elements
units = f['main_data'].attrs['units']
print(f"Group content: {list(f['subgroup'].keys())}")
关键规则
✅ 应该做
- 使用上下文管理器 - 始终使用
with h5py.File(...) as f:,确保即使发生错误也会关闭文件。 - 使用分块 - 对于大型数据集,指定
chunks=True或手动设置形状,以针对特定切片模式优化访问速度。 - 启用压缩 - 使用
compression="gzip"为大型数值数组节省磁盘空间。 - 使用描述性名称 - 使用组对数据进行逻辑组织(例如,
/experiment1/sensorA/raw)。 - 在属性中存储元数据 - 不要为单位或时间戳创建单独的文本文件;应将它们附加到数据集上。
- 检查成员是否存在 - 访问前使用
"name" in group,以避免 KeyError。
❌ 不应该做
- 误用 'w' 模式打开文件 - 'w' 模式会覆盖现有文件。请改用 'a'(追加/读写)或 'r+'(读写)。
- 将整个数据集加载到 RAM - 除非确定数据集能放入内存,否则避免使用
data = f['large_dataset'][:]。 - 存储数千个小型数据集 - HDF5 针对大型数组进行了优化。对于数百万个微小标量,请使用单个数组或其他数据库。
- 忘记关闭文件 - 未关闭的 HDF5 文件可能会损坏或被锁定。
反模式(绝不要这样做)
import h5py
import numpy as np
# ❌ BAD: Manual file closing (unsafe)
f = h5py.File('data.h5', 'w')
f.create_dataset('x', data=np.arange(10))
f.close() # If an error happened above, this never runs!
# ✅ GOOD: Context manager
with h5py.File('data.h5', 'w') as f:
f.create_dataset('x', data=np.arange(10))
# ❌ BAD: Storing metadata as strings inside a dataset
f.create_dataset('meta', data=np.array(['unit: meter', 'date: 2024']))
# ✅ GOOD: Using Attributes
dset = f.create_dataset('data', data=np.random.rand(10))
dset.attrs['unit'] = 'meter'
dset.attrs['date'] = '2024'
# ❌ BAD: Inefficient chunking (one row at a time when you read columns)
# f.create_dataset('big', shape=(10000, 10000), chunks=(1, 10000))
数据集创建与配置
高级选项
with h5py.File('optimized.h5', 'w') as f:
# 1. Resizable dataset (maxshape)
dset = f.create_dataset('growing',
shape=(100,),
maxshape=(None,), # Allow growth in 1st dimension
dtype='float32')
# 2. Compression and Chunking
f.create_dataset('compressed',
data=np.random.randn(1000, 1000),
chunks=(100, 100),
compression="gzip",
compression_opts=4) # 4 is a good balance
# 3. Filling with default values
f.create_dataset('default', shape=(10, 10), fillvalue=-1.0)
使用组
导航和迭代
with h5py.File('nested.h5', 'w') as f:
f.create_group('raw/2024/january')
f.create_group('raw/2024/february')
# Recursive iteration
def print_structure(name, obj):
print(name)
with h5py.File('nested.h5', 'r') as f:
f.visititems(print_structure) # Visits every dataset and group
# Accessing via path
feb_data = f['/raw/2024/february']
性能优化
1. 分块策略
块是可读取或写入的最小数据单位。
- 如果通常逐行读取:
chunks=(1, n_cols)。 - 如果读取数据块:
chunks=(100, 100)。 - 如果不确定:
chunks=True可让 h5py 自动推测。
2. SWMR(单写入者多读取者)
允许写入者向文件追加内容,同时其他进程实时读取该文件。
# Writer
f = h5py.File('live.h5', 'w', libver='latest')
f.swmr_mode = True
# Reader
f = h5py.File('live.h5', 'r', libver='latest', swmr=True)
3. Core 驱动程序(内存中的 HDF5)
使用 HDF5 结构,但将其完全保留在 RAM 中以提升速度,并可选择保存到磁盘。
# Create an HDF5 file in memory
f = h5py.File('memfile.h5', 'w', driver='core', backing_store=True)
实用工作流
1. 存储机器学习训练数据
def save_ml_dataset(X, y, filename):
with h5py.File(filename, 'w') as f:
# Create datasets for images and labels
f.create_dataset('images', data=X, compression="lzf") # LZF is fast
f.create_dataset('labels', data=y)
# Add metadata
f.attrs['n_samples'] = X.shape[0]
f.attrs['input_shape'] = X.shape[1:]
f.attrs['classes'] = np.unique(y)
# Use cases: training on data that exceeds RAM
2. 大型模拟记录器
def log_simulation_step(filename, step_idx, data_array):
with h5py.File(filename, 'a') as f:
if 'simulation' not in f:
# Initialize resizable dataset
f.create_dataset('simulation',
shape=(0, *data_array.shape),
maxshape=(None, *data_array.shape),
chunks=(1, *data_array.shape))
dset = f['simulation']
dset.resize(step_idx + 1, axis=0)
dset[step_idx] = data_array
3. 批量图像存储
def store_images(image_files, h5_file):
with h5py.File(h5_file, 'w') as f:
grp = f.create_group('microscopy_data')
for i, img_path in enumerate(image_files):
# Load your image here
img_data = np.random.rand(512, 512)
dset = grp.create_dataset(f'img_{i:04d}', data=img_data)
dset.attrs['original_path'] = img_path
常见问题与解决方案
“数据集已存在”错误
# ❌ Problem: f.create_dataset('x', ...) fails if 'x' exists
# ✅ Solution: Delete first or use a check
if 'x' in f:
del f['x']
f.create_dataset('x', data=new_data)
文件锁定问题
# ❌ Problem: "OSError: Unable to open file (file locking disabled on this file system)"
# This often happens on network drives (NFS).
# ✅ Solution: Set environment variable before running script
import os
os.environ['HDF5_USE_FILE_LOCKING'] = 'FALSE'
import h5py
存储 Unicode 字符串
HDF5 对字符串的支持很复杂。
# ❌ Problem: Storing lists of strings can sometimes cause issues in older versions
# ✅ Solution: Use special string types
dt = h5py.string_dtype(encoding='utf-8')
dset = f.create_dataset('strings', (100,), dtype=dt)
dset[0] = "Научные данные"
h5py 是处理大型数值数据的工业级方式。通过结合 NumPy 的灵活性和 HDF5 的强大功能,它能确保您的科学数据井然有序、易于访问且处理迅速。
评论
支持 Markdown