oafuncs 0.0.59__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
oafuncs/oa_file.py ADDED
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ '''
4
+ Author: Liu Kun && 16031215@qq.com
5
+ Date: 2024-09-17 15:07:13
6
+ LastEditors: Liu Kun && 16031215@qq.com
7
+ LastEditTime: 2024-11-11 16:11:23
8
+ FilePath: \\Python\\My_Funcs\\OAFuncs\\OAFuncs\\oa_file.py
9
+ Description:
10
+ EditPlatform: vscode
11
+ ComputerInfo: XPS 15 9510
12
+ SystemInfo: Windows 11
13
+ Python Version: 3.11
14
+ '''
15
+
16
+
17
+ import glob
18
+ import os
19
+ import re
20
+ import shutil
21
+
22
+ __all__ = ['link_file', 'copy_file', 'rename_files', 'make_folder',
23
+ 'clear_folder', 'remove_empty_folders', 'remove', 'file_size']
24
+
25
+
26
+ def link_file(src_pattern, dst):
27
+ '''
28
+ # 描述:创建符号链接,支持通配符
29
+ # 使用示例
30
+ # link_file(r'/data/hejx/liukun/era5/*', r'/data/hejx/liukun/Test/')
31
+ # link_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test/py.o')
32
+ # link_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test')
33
+ param {*} src_pattern # 源文件或目录
34
+ param {*} dst # 目标文件或目录
35
+ '''
36
+ src_pattern= str(src_pattern)
37
+ # 使用glob.glob来处理可能包含通配符的src
38
+ src_files= glob.glob(src_pattern)
39
+ if not src_files:
40
+ raise FileNotFoundError('文件不存在: {}'.format(src_pattern))
41
+
42
+ # 判断dst是路径还是包含文件名的路径
43
+ if os.path.isdir(dst):
44
+ # 如果dst是路径,则保持源文件的文件名
45
+ dst_dir= dst
46
+ for src_file in src_files:
47
+ src_file_basename= os.path.basename(src_file)
48
+ dst_file= os.path.join(dst_dir, src_file_basename)
49
+ if os.path.exists(dst_file):
50
+ os.remove(dst_file)
51
+ os.symlink(src_file, dst_file)
52
+ print(f'创建符号链接: {src_file} -> {dst_file}')
53
+ else:
54
+ # 如果dst包含文件名,则创建链接后重命名
55
+ dst_dir= os.path.dirname(dst)
56
+ os.makedirs(dst_dir, exist_ok=True)
57
+ # 只处理第一个匹配的文件
58
+ src_file= src_files[0]
59
+ dst_file= dst
60
+ if os.path.exists(dst_file):
61
+ os.remove(dst_file)
62
+ os.symlink(src_file, dst_file)
63
+ print(f'创建符号链接并重命名: {src_file} -> {dst_file}')
64
+
65
+
66
+ def copy_file(src_pattern, dst):
67
+ '''
68
+ # 描述:复制文件或目录,支持通配符
69
+ # 使用示例
70
+ # copy_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test/py.o')
71
+ # copy_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test')
72
+ param {*} src_pattern # 源文件或目录
73
+ param {*} dst # 目标文件或目录
74
+ '''
75
+ src_pattern= str(src_pattern)
76
+ # 使用glob.glob来处理可能包含通配符的src
77
+ src_files= glob.glob(src_pattern)
78
+ if not src_files:
79
+ raise FileNotFoundError('文件不存在: {}'.format(src_pattern))
80
+
81
+ # 判断dst是路径还是包含文件名的路径
82
+ if os.path.isdir(dst):
83
+ # 如果dst是路径,则保持源文件的文件名
84
+ dst_dir= dst
85
+ for src_file in src_files:
86
+ src_file_basename= os.path.basename(src_file)
87
+ dst_file= os.path.join(dst_dir, src_file_basename)
88
+ if os.path.exists(dst_file):
89
+ if os.path.isdir(dst_file):
90
+ shutil.rmtree(dst_file)
91
+ else:
92
+ os.remove(dst_file)
93
+ if os.path.isdir(src_file):
94
+ shutil.copytree(src_file, dst_file, symlinks=True)
95
+ else:
96
+ shutil.copy2(src_file, dst_file)
97
+ print(f'复制文件或目录: {src_file} -> {dst_file}')
98
+ else:
99
+ # 如果dst包含文件名,则复制后重命名
100
+ dst_dir= os.path.dirname(dst)
101
+ os.makedirs(dst_dir, exist_ok=True)
102
+ # 只处理第一个匹配的文件
103
+ src_file= src_files[0]
104
+ dst_file= dst
105
+ if os.path.exists(dst_file):
106
+ if os.path.isdir(dst_file):
107
+ shutil.rmtree(dst_file)
108
+ else:
109
+ os.remove(dst_file)
110
+ if os.path.isdir(src_file):
111
+ shutil.copytree(src_file, dst_file, symlinks=True)
112
+ else:
113
+ shutil.copy2(src_file, dst_file)
114
+ print(f'复制文件或目录并重命名: {src_file} -> {dst_file}')
115
+
116
+
117
+ def rename_files(directory, old_str, new_str):
118
+ '''
119
+ # 描述:重命名目录下的文件,支持通配符
120
+ # 使用示例
121
+ directory_path = r"E:\windfarm\CROCO_FILES"
122
+ old_str = "croco"
123
+ new_str = "roms"
124
+ rename_files(directory_path, old_str, new_str)
125
+ param {*} directory # 目录
126
+ param {*} old_str # 要替换的字符串
127
+ param {*} new_str # 新字符串
128
+ '''
129
+ # 获取目录下的所有文件
130
+ files= os.listdir(directory)
131
+
132
+ # 构建正则表达式以匹配要替换的字符串
133
+ pattern= re.compile(re.escape(old_str))
134
+
135
+ # 遍历目录下的文件
136
+ for filename in files:
137
+ # 检查文件名中是否包含要替换的字符串
138
+ if pattern.search(filename):
139
+ # 构建新的文件名
140
+ new_filename= pattern.sub(new_str, filename)
141
+
142
+ # 构建旧文件的完整路径
143
+ old_path= os.path.join(directory, filename)
144
+
145
+ # 构建新文件的完整路径
146
+ new_path= os.path.join(directory, new_filename)
147
+
148
+ # 重命名文件
149
+ os.rename(old_path, new_path)
150
+ print(f"重命名文件: {old_path} -> {new_path}")
151
+
152
+
153
+ # ** 创建子文件夹(可选清空)
154
+ def make_folder(rootpath: str, folder_name: str, clear=0) -> str:
155
+ '''
156
+ # 描述:创建子文件夹(可选清空)
157
+ # 使用示例
158
+ rootpath = r'E:\Data\2024\09\17'
159
+ folder_name = 'var1'
160
+ newpath = make_folder(rootpath, folder_name, clear=1)
161
+ param {*} rootpath # 根目录
162
+ param {*} folder_name # 文件夹名称
163
+ '''
164
+ folder_path= os.path.join(str(rootpath), str(folder_name))
165
+ if clear:
166
+ shutil.rmtree(folder_path, ignore_errors=True)
167
+ os.makedirs(folder_path, exist_ok=True)
168
+ return folder_path
169
+
170
+ # ** 清空文件夹
171
+
172
+
173
+ def clear_folder(folder_path):
174
+ '''
175
+ # 描述:清空文件夹
176
+ # 使用示例
177
+ clear_folder(r'E:\Data\2024\09\17\var1')
178
+ param {*} folder_path # 文件夹路径
179
+ '''
180
+ folder_path= str(folder_path)
181
+ if os.path.exists(folder_path):
182
+ try:
183
+ # 遍历文件夹中的所有文件和子文件夹
184
+ for filename in os.listdir(folder_path):
185
+ file_path= os.path.join(folder_path, filename)
186
+ # 判断是文件还是文件夹
187
+ if os.path.isfile(file_path) or os.path.islink(file_path):
188
+ os.unlink(file_path) # 删除文件或链接
189
+ elif os.path.isdir(file_path):
190
+ shutil.rmtree(file_path) # 删除子文件夹
191
+ print(f'成功清空文件夹: {folder_path}')
192
+ except Exception as e:
193
+ print(f'清空文件夹失败: {folder_path}')
194
+ print(e)
195
+
196
+
197
+ # ** 清理空文件夹
198
+ def remove_empty_folders(path, print_info=1):
199
+ '''
200
+ # 描述:清理空文件夹
201
+ # 使用示例
202
+ remove_empty_folders(r'E:\Data\2024\09\17', print_info=1)
203
+ param {*} path # 文件夹路径
204
+ param {*} print_info # 是否打印信息
205
+ '''
206
+ path= str(path)
207
+ # 遍历当前目录下的所有文件夹和文件
208
+ for root, dirs, files in os.walk(path, topdown=False):
209
+ # 遍历文件夹列表
210
+ for folder in dirs:
211
+ folder_path= os.path.join(root, folder)
212
+ # 判断文件是否有权限访问
213
+ try:
214
+ os.listdir(folder_path)
215
+ except OSError:
216
+ continue
217
+ # 判断文件夹是否为空
218
+ if not os.listdir(folder_path):
219
+ # 删除空文件夹
220
+ try:
221
+ os.rmdir(folder_path)
222
+ print(f"Deleted empty folder: {folder_path}")
223
+ except OSError:
224
+ if print_info:
225
+ print(f"Skipping protected folder: {folder_path}")
226
+ pass
227
+
228
+
229
+ # ** 删除相关文件,可使用通配符
230
+ def remove(pattern):
231
+ '''
232
+ # 描述:删除相关文件,可使用通配符
233
+ remove(r'E:\Code\Python\Model\WRF\Radar2\bzip2-radar-0*')
234
+ # or
235
+ os.chdir(r'E:\Code\Python\Model\WRF\Radar2')
236
+ remove('bzip2-radar-0*')
237
+ param {*} pattern # 文件路径或通配符
238
+ '''
239
+ # 使用glob.glob来获取所有匹配的文件
240
+ # 可以使用通配符*来匹配所有文件
241
+ pattern= str(pattern)
242
+ file_list= glob.glob(pattern)
243
+ for file_path in file_list:
244
+ if os.path.exists(file_path):
245
+ try:
246
+ shutil.rmtree(file_path)
247
+ print(f'成功删除文件: {file_path}')
248
+ except Exception as e:
249
+ print(f'删除文件失败: {file_path}')
250
+ print(e)
251
+ else:
252
+ print(f'文件不存在: {file_path}')
253
+
254
+
255
+ def file_size(file_path, unit='KB'):
256
+ '''
257
+ Description: 获取文件大小
258
+
259
+ Args:
260
+ file_path: 文件路径
261
+ unit: 单位(PB、TB、GB、MB、KB)
262
+
263
+ Returns:
264
+ 文件大小(单位:PB、TB、GB、MB、KB)
265
+ '''
266
+ # 检查文件是否存在
267
+ if not os.path.exists(file_path):
268
+ return "文件不存在"
269
+
270
+ # 获取文件大小(字节)
271
+ file_size= os.path.getsize(file_path)
272
+
273
+ # 单位转换字典
274
+ unit_dict= {
275
+ 'PB': 1024**5,
276
+ 'TB': 1024**4,
277
+ 'GB': 1024**3,
278
+ 'MB': 1024**2,
279
+ 'KB': 1024
280
+ }
281
+
282
+ # 检查传入的单位是否合法
283
+ if unit not in unit_dict:
284
+ return "单位不合法,请选择PB、TB、GB、MB、KB中的一个"
285
+
286
+ # 转换文件大小到指定单位
287
+ converted_size= file_size / unit_dict[unit]
288
+
289
+ return converted_size
290
+
291
+
292
+ if __name__ == '__main__':
293
+ # newpath = make_folder('D:/Data/2024/09/17/', 'var1', clear=1)
294
+ # print(newpath)
295
+ pass
296
+
297
+ remove(r'I:\Delete\test\*')
oafuncs/oa_help.py ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ '''
4
+ Author: Liu Kun && 16031215@qq.com
5
+ Date: 2024-10-06 19:25:29
6
+ LastEditors: Liu Kun && 16031215@qq.com
7
+ LastEditTime: 2024-10-06 19:55:04
8
+ FilePath: \\Python\\My_Funcs\\OAFuncs\\OAFuncs\\oa_help.py
9
+ Description:
10
+ EditPlatform: vscode
11
+ ComputerInfo: XPS 15 9510
12
+ SystemInfo: Windows 11
13
+ Python Version: 3.11
14
+ '''
15
+
16
+ import OAFuncs
17
+
18
+
19
+ def query():
20
+ '''
21
+ description: 查看OAFuncs模块的函数列表
22
+ example: query()
23
+ '''
24
+ funcs = [func for func in dir(OAFuncs) if callable(getattr(OAFuncs, func))]
25
+ print('函数数量:')
26
+ print(len(funcs))
27
+ print('函数列表:')
28
+ print(funcs)
29
+
30
+
31
+ def use(func='get_var'):
32
+ '''
33
+ description: 查看函数的模块全路径和函数提示
34
+ param {func} : 函数名
35
+ example: use('get_var')
36
+ '''
37
+ print('模块全路径:')
38
+ print(getattr(OAFuncs, func).__module__+'.'+func)
39
+ print('函数提示:')
40
+ print(getattr(OAFuncs, func).__doc__)
oafuncs/oa_nc.py ADDED
@@ -0,0 +1,345 @@
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ '''
4
+ Author: Liu Kun && 16031215@qq.com
5
+ Date: 2024-09-17 14:58:50
6
+ LastEditors: Liu Kun && 16031215@qq.com
7
+ LastEditTime: 2024-11-05 16:44:20
8
+ FilePath: \\Python\\My_Funcs\\OAFuncs\\OAFuncs\\oa_nc.py
9
+ Description:
10
+ EditPlatform: vscode
11
+ ComputerInfo: XPS 15 9510
12
+ SystemInfo: Windows 11
13
+ Python Version: 3.11
14
+ '''
15
+
16
+
17
+ import os
18
+
19
+ import netCDF4 as nc
20
+ import numpy as np
21
+ import xarray as xr
22
+
23
+ __all__ = ['get_var', 'extract5nc', 'write2nc',
24
+ 'merge5nc', 'modify_var_value', 'modify_var_attr', 'rename_var_or_dim', 'check_ncfile']
25
+
26
+
27
+ def get_var(file, *vars):
28
+ '''
29
+ description: 读取nc文件中的变量
30
+ param {file: 文件路径, *vars: 变量名}
31
+ example: datas = get_var(file_ecm, 'h', 't', 'u', 'v')
32
+ return {datas: 变量数据}
33
+ '''
34
+ ds = xr.open_dataset(file)
35
+ datas = []
36
+ for var in vars:
37
+ data = ds[var]
38
+ datas.append(data)
39
+ ds.close()
40
+ return datas
41
+
42
+
43
+ def extract5nc(file, varname):
44
+ '''
45
+ 描述:
46
+ 1、提取nc文件中的变量
47
+ 2、将相应维度提取,建立字典
48
+ return:返回变量及坐标字典
49
+ 参数:
50
+ file: 文件路径
51
+ varname: 变量名
52
+ example: data, dimdict = extract5nc(file_ecm, 'h')
53
+ '''
54
+ ds = xr.open_dataset(file)
55
+ vardata = ds[varname]
56
+ dims = vardata.dims
57
+ dimdict = {}
58
+ for dim in dims:
59
+ dimdict[dim] = ds[dim].values
60
+ ds.close()
61
+ return np.array(vardata), dimdict
62
+
63
+
64
+ def _numpy_to_nc_type(numpy_type):
65
+ """将NumPy数据类型映射到NetCDF数据类型"""
66
+ numpy_to_nc = {
67
+ 'float32': 'f4',
68
+ 'float64': 'f8',
69
+ 'int8': 'i1',
70
+ 'int16': 'i2',
71
+ 'int32': 'i4',
72
+ 'int64': 'i8',
73
+ 'uint8': 'u1',
74
+ 'uint16': 'u2',
75
+ 'uint32': 'u4',
76
+ 'uint64': 'u8',
77
+ }
78
+ return numpy_to_nc.get(str(numpy_type), 'f4') # 默认使用 'float32'
79
+
80
+
81
+ def write2nc(file, data, varname, coords, mode):
82
+ '''
83
+ description: 写入数据到nc文件
84
+ 参数:
85
+ file: 文件路径
86
+ data: 数据
87
+ varname: 变量名
88
+ coords: 坐标,字典,键为维度名称,值为坐标数据
89
+ mode: 写入模式,'w'为写入,'a'为追加
90
+ example: write2nc(r'test.nc', data, 'data', {'time': np.linspace(0, 120, 100), 'lev': np.linspace(0, 120, 50)}, 'a')
91
+ '''
92
+ # 判断mode是写入还是追加
93
+ if mode == 'w':
94
+ if os.path.exists(file):
95
+ os.remove(file)
96
+ print("Warning: File already exists. Deleting it.")
97
+ elif mode == 'a':
98
+ if not os.path.exists(file):
99
+ print("Warning: File doesn't exist. Creating a new file.")
100
+ mode = 'w'
101
+
102
+ # 打开 NetCDF 文件
103
+ with nc.Dataset(file, mode, format="NETCDF4") as ncfile:
104
+ # 处理坐标
105
+ for dim, coord_data in coords.items():
106
+ add_coords = True
107
+ # 判断坐标是否存在,若存在,则替换/报错
108
+ if ncfile.dimensions:
109
+ # 返回字典,字典、列表、元组若为空,都表示False
110
+ if dim in ncfile.dimensions:
111
+ # del nc.dimensions[dim]
112
+ if len(coord_data) != len(ncfile.dimensions[dim]):
113
+ raise ValueError(
114
+ "Length of coordinate does not match the dimension length.")
115
+ else:
116
+ add_coords = False
117
+ print(
118
+ f"Warning: Coordinate '{dim}' already exists. Replacing it.")
119
+ ncfile.variables[dim][:] = np.array(coord_data)
120
+ if add_coords:
121
+ # 创建新坐标
122
+ ncfile.createDimension(dim, len(coord_data))
123
+ ncfile.createVariable(dim, _numpy_to_nc_type(
124
+ coord_data.dtype), (dim,))
125
+ ncfile.variables[dim][:] = np.array(coord_data)
126
+
127
+ # 判断变量是否存在,若存在,则删除原变量
128
+ add_var = True
129
+ if varname in ncfile.variables:
130
+ print(f"Warning: Variable '{varname}' already exists.")
131
+ if data.shape != ncfile.variables[varname].shape:
132
+ raise ValueError(
133
+ "Shape of data does not match the variable shape.")
134
+ else:
135
+ # 写入数据
136
+ ncfile.variables[varname][:] = data
137
+ add_var = False
138
+ print(
139
+ f"Warning: Variable '{varname}' already exists. Replacing it.")
140
+
141
+ if add_var:
142
+ # 创建变量及其维度
143
+ dim_names = tuple(coords.keys()) # 使用coords传入的维度名称
144
+ ncfile.createVariable(
145
+ varname, _numpy_to_nc_type(data.dtype), dim_names)
146
+ # ncfile.createVariable('data', 'f4', ('time','lev'))
147
+
148
+ # 写入数据
149
+ ncfile.variables[varname][:] = data
150
+
151
+ # 判断维度是否匹配
152
+ if len(data.shape) != len(coords):
153
+ raise ValueError(
154
+ "Number of dimensions does not match the data shape.")
155
+
156
+
157
+ def merge5nc(file_list, var_name, dim_name, target_filename):
158
+ """
159
+ 批量提取 nc 文件中的某一变量,按照某一维度合并后写入新的 nc 文件。
160
+
161
+ 参数:
162
+ file_list:nc 文件路径列表
163
+ var_name:要提取的变量名
164
+ dim_name:用于合并的维度名
165
+ target_filename:合并后的目标文件名
166
+ example: merge5nc(file_list, 'sst', 'time', 'merged_data.nc')
167
+ """
168
+ data_list = []
169
+ for i, file in enumerate(file_list):
170
+ print(f"\rReading file {i + 1}/{len(file_list)}...", end="")
171
+ ds = xr.open_dataset(file)
172
+ var = ds[var_name]
173
+ data_list.append(var)
174
+ ds.close()
175
+ print("\nMerging data...")
176
+ data = xr.concat(data_list, dim=dim_name)
177
+ print("Writing data to file...")
178
+ if os.path.exists(target_filename):
179
+ print("Warning: The target file already exists.")
180
+ print("Removing existing file...")
181
+ os.remove(target_filename)
182
+ data.to_netcdf(target_filename)
183
+
184
+
185
+ def merge5nc_vars(file_list, var_names, dim_name, target_filename):
186
+ """
187
+ 批量提取 nc 文件中的两个变量,按照某一维度合并后写入新的 nc 文件。
188
+
189
+ 参数:
190
+ file_list:nc 文件路径列表
191
+ var_names:要提取的变量名列表,例如 ['u', 'v']
192
+ dim_name:用于合并的维度名
193
+ target_filename:合并后的目标文件名
194
+
195
+ example: merge5nc_vars(file_list, ['u', 'v'], 'time', 'merged_data.nc')
196
+ """
197
+ data_lists = [[] for _ in var_names]
198
+ for i, file in enumerate(file_list):
199
+ print(f"\rReading file {i + 1}/{len(file_list)}...", end="")
200
+ ds = xr.open_dataset(file)
201
+ for j, var_name in enumerate(var_names):
202
+ var = ds[var_name]
203
+ data_lists[j].append(var)
204
+ ds.close()
205
+ print("\nMerging data...")
206
+ merged_data = {}
207
+ for var_name, data_list in zip(var_names, data_lists):
208
+ merged_data[var_name] = xr.concat(data_list, dim=dim_name)
209
+ print("Writing data to file...")
210
+ ds_merged = xr.Dataset(merged_data)
211
+ if os.path.exists(target_filename):
212
+ print("Warning: The target file already exists.")
213
+ print("Removing existing file...")
214
+ os.remove(target_filename)
215
+ ds_merged.to_netcdf(target_filename)
216
+
217
+
218
+ def modify_var_value(nc_file_path, variable_name, new_value):
219
+ """
220
+ 使用 netCDF4 库修改 NetCDF 文件中特定变量的值
221
+
222
+ 参数:
223
+ nc_file_path (str): NetCDF 文件路径
224
+ variable_name (str): 要修改的变量名
225
+ new_value (numpy.ndarray): 新的变量值
226
+
227
+ example: modify_var_value('test.nc', 'data', np.random.rand(100, 50))
228
+ """
229
+ try:
230
+ # Open the NetCDF file
231
+ dataset = nc.Dataset(nc_file_path, 'r+')
232
+ # Get the variable to be modified
233
+ variable = dataset.variables[variable_name]
234
+ # Modify the value of the variable
235
+ variable[:] = new_value
236
+ dataset.close()
237
+ print(
238
+ f"Successfully modified variable {variable_name} in {nc_file_path}.")
239
+ except Exception as e:
240
+ print(
241
+ f"An error occurred while modifying variable {variable_name} in {nc_file_path}: {e}")
242
+
243
+
244
+ def modify_var_attr(nc_file_path, variable_name, attribute_name, attribute_value):
245
+ """
246
+ 使用 netCDF4 库添加或修改 NetCDF 文件中特定变量的属性。
247
+
248
+ 参数:
249
+ nc_file_path (str): NetCDF 文件路径
250
+ variable_name (str): 要操作的变量名
251
+ attribute_name (str): 属性名
252
+ attribute_value (任意类型): 属性值
253
+ example: modify_var_attr('test.nc', 'data', 'long_name', 'This is a test variable.')
254
+ """
255
+ try:
256
+ ds = nc.Dataset(nc_file_path, 'r+')
257
+ if variable_name not in ds.variables:
258
+ raise ValueError(
259
+ f"Variable '{variable_name}' not found in the NetCDF file.")
260
+
261
+ variable = ds.variables[variable_name]
262
+ if attribute_name in variable.ncattrs():
263
+ print(
264
+ f"Warning: Attribute '{attribute_name}' already exists. Replacing it.")
265
+ variable.setncattr(attribute_name, attribute_value)
266
+ else:
267
+ print(f"Adding attribute '{attribute_name}'...")
268
+ variable.setncattr(attribute_name, attribute_value)
269
+
270
+ ds.close()
271
+ except Exception as e:
272
+ raise RuntimeError(f"An error occurred: {e}")
273
+
274
+
275
+ def rename_var_or_dim(ncfile_path, old_name, new_name):
276
+ """
277
+ Rename a variable and/or dimension in a NetCDF file.
278
+
279
+ Parameters:
280
+ ncfile_path (str): The path to the NetCDF file.
281
+ old_name (str): The name of the variable or dimension to be renamed.
282
+ new_name (str): The new name for the variable or dimension.
283
+
284
+ example: rename_var_or_dim('test.nc', 'time', 'ocean_time')
285
+ """
286
+ try:
287
+ with nc.Dataset(ncfile_path, 'r+') as dataset:
288
+ # If the old name is not found as a variable or dimension, print a message
289
+ if old_name not in dataset.variables and old_name not in dataset.dimensions:
290
+ print(
291
+ f"Variable or dimension {old_name} not found in the file.")
292
+
293
+ # Attempt to rename the variable
294
+ if old_name in dataset.variables:
295
+ dataset.renameVariable(old_name, new_name)
296
+ print(
297
+ f"Successfully renamed variable {old_name} to {new_name}.")
298
+
299
+ # Attempt to rename the dimension
300
+ if old_name in dataset.dimensions:
301
+ # Check if the new dimension name already exists
302
+ if new_name in dataset.dimensions:
303
+ raise ValueError(
304
+ f"Dimension name {new_name} already exists in the file.")
305
+ dataset.renameDimension(old_name, new_name)
306
+ print(
307
+ f"Successfully renamed dimension {old_name} to {new_name}.")
308
+
309
+ except Exception as e:
310
+ print(f"An error occurred: {e}")
311
+
312
+
313
+ def check_ncfile(ncfile, if_delete=False):
314
+ if not os.path.exists(ncfile):
315
+ return False
316
+
317
+ try:
318
+ with nc.Dataset(ncfile, 'r') as f:
319
+ # 确保f被使用,这里我们检查文件中变量的数量
320
+ if len(f.variables) > 0:
321
+ return True
322
+ else:
323
+ # 如果没有变量,我们可以认为文件是损坏的
324
+ raise ValueError("File is empty or corrupted.")
325
+ except OSError as e:
326
+ # 捕获文件打开时可能发生的OSError
327
+ print(f"An error occurred while opening the file: {e}")
328
+ if if_delete:
329
+ os.remove(ncfile)
330
+ print(f"File {ncfile} has been deleted.")
331
+ return False
332
+ except Exception as e:
333
+ # 捕获其他可能的异常
334
+ print(f"An unexpected error occurred: {e}")
335
+ if if_delete:
336
+ os.remove(ncfile)
337
+ print(f"File {ncfile} has been deleted.")
338
+ return False
339
+
340
+
341
+ if __name__ == '__main__':
342
+
343
+ data = np.random.rand(100, 50)
344
+ write2nc(r'test.nc', data,
345
+ 'data', {'time': np.linspace(0, 120, 100), 'lev': np.linspace(0, 120, 50)}, 'a')