oafuncs 0.0.97.1__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/__init__.py +54 -0
- oafuncs/_script/__init__.py +27 -0
- oafuncs/_script/plot_dataset.py +299 -0
- oafuncs/data_store/OAFuncs.png +0 -0
- oafuncs/data_store/hycom_3hourly.png +0 -0
- oafuncs/oa_cmap.py +215 -0
- oafuncs/oa_data.py +293 -0
- oafuncs/oa_down/User_Agent-list.txt +6697 -0
- oafuncs/oa_down/__init__.py +22 -0
- oafuncs/oa_down/hycom_3hourly.py +1309 -0
- oafuncs/oa_down/hycom_3hourly_20250129.py +1307 -0
- oafuncs/oa_down/idm.py +50 -0
- oafuncs/oa_down/literature.py +288 -0
- oafuncs/oa_down/test_ua.py +151 -0
- oafuncs/oa_down/user_agent.py +31 -0
- oafuncs/oa_draw.py +326 -0
- oafuncs/oa_file.py +413 -0
- oafuncs/oa_help.py +144 -0
- oafuncs/oa_model/__init__.py +19 -0
- oafuncs/oa_model/roms/__init__.py +20 -0
- oafuncs/oa_model/roms/test.py +19 -0
- oafuncs/oa_model/wrf/__init__.py +18 -0
- oafuncs/oa_model/wrf/little_r.py +186 -0
- oafuncs/oa_nc.py +523 -0
- oafuncs/oa_python.py +108 -0
- oafuncs/oa_sign/__init__.py +21 -0
- oafuncs/oa_sign/meteorological.py +168 -0
- oafuncs/oa_sign/ocean.py +158 -0
- oafuncs/oa_sign/scientific.py +139 -0
- oafuncs/oa_tool/__init__.py +19 -0
- oafuncs/oa_tool/email.py +114 -0
- oafuncs/oa_tool/parallel.py +90 -0
- oafuncs/oa_tool/time.py +22 -0
- oafuncs-0.0.97.1.dist-info/LICENSE.txt +19 -0
- oafuncs-0.0.97.1.dist-info/METADATA +106 -0
- oafuncs-0.0.97.1.dist-info/RECORD +38 -0
- oafuncs-0.0.97.1.dist-info/WHEEL +5 -0
- oafuncs-0.0.97.1.dist-info/top_level.txt +1 -0
oafuncs/oa_file.py
ADDED
@@ -0,0 +1,413 @@
|
|
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-12-13 16:28:56
|
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
|
+
import glob
|
17
|
+
import os
|
18
|
+
import re
|
19
|
+
import shutil
|
20
|
+
from rich import print
|
21
|
+
|
22
|
+
__all__ = ["find_file", "link_file", "copy_file", "rename_file", "make_folder", "clear_folder", "remove_empty_folder", "remove", "file_size", "mean_size", "make_dir"]
|
23
|
+
|
24
|
+
|
25
|
+
# ** 查找文件,支持通配符
|
26
|
+
def find_file(parent_path, fname, mode="path"):
|
27
|
+
"""
|
28
|
+
description:
|
29
|
+
param {*} parent_path: The parent path where the files are located
|
30
|
+
param {*} fname: The file name pattern to search for
|
31
|
+
param {*} mode: 'path' to return the full path of the files, 'file' to return only the file names
|
32
|
+
return {*} A list of file paths or file names if files are found, None otherwise
|
33
|
+
"""
|
34
|
+
|
35
|
+
def natural_sort_key(s):
|
36
|
+
"""生成一个用于自然排序的键"""
|
37
|
+
return [int(text) if text.isdigit() else text.lower() for text in re.split("([0-9]+)", s)]
|
38
|
+
|
39
|
+
# 将parent_path和fname结合成完整的搜索路径
|
40
|
+
search_pattern = os.path.join(str(parent_path), fname)
|
41
|
+
|
42
|
+
# 使用glob模块查找所有匹配的文件
|
43
|
+
matched_files = glob.glob(search_pattern)
|
44
|
+
|
45
|
+
# 如果没有找到任何文件,则返回False
|
46
|
+
if not matched_files:
|
47
|
+
return None
|
48
|
+
|
49
|
+
# 在find_files函数中替换natsorted调用
|
50
|
+
matched_files = sorted(matched_files, key=natural_sort_key)
|
51
|
+
|
52
|
+
# 根据mode参数决定返回的内容
|
53
|
+
if mode == "file":
|
54
|
+
# 只返回文件名
|
55
|
+
result = [os.path.basename(file) for file in matched_files]
|
56
|
+
else: # 默认为'path'
|
57
|
+
# 返回文件的绝对路径
|
58
|
+
result = [os.path.abspath(file) for file in matched_files]
|
59
|
+
|
60
|
+
return result
|
61
|
+
|
62
|
+
|
63
|
+
# ** 创建符号链接,支持通配符
|
64
|
+
def link_file(src_pattern, dst):
|
65
|
+
"""
|
66
|
+
# 描述:创建符号链接,支持通配符
|
67
|
+
# 使用示例
|
68
|
+
# link_file(r'/data/hejx/liukun/era5/*', r'/data/hejx/liukun/Test/')
|
69
|
+
# link_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test/py.o')
|
70
|
+
# link_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test')
|
71
|
+
param {*} src_pattern # 源文件或目录
|
72
|
+
param {*} dst # 目标文件或目录
|
73
|
+
"""
|
74
|
+
src_pattern = str(src_pattern)
|
75
|
+
# 使用glob.glob来处理可能包含通配符的src
|
76
|
+
src_files = glob.glob(src_pattern)
|
77
|
+
if not src_files:
|
78
|
+
raise FileNotFoundError("File does not exist: {}".format(src_pattern))
|
79
|
+
|
80
|
+
# 判断dst是路径还是包含文件名的路径
|
81
|
+
if os.path.isdir(dst):
|
82
|
+
# 如果dst是路径,则保持源文件的文件名
|
83
|
+
dst_dir = dst
|
84
|
+
for src_file in src_files:
|
85
|
+
src_file_basename = os.path.basename(src_file)
|
86
|
+
dst_file = os.path.join(dst_dir, src_file_basename)
|
87
|
+
if os.path.exists(dst_file):
|
88
|
+
os.remove(dst_file)
|
89
|
+
os.symlink(src_file, dst_file)
|
90
|
+
# print(f"创建符号链接: {src_file} -> {dst_file}")
|
91
|
+
print(f"Create a symbolic link: {src_file} -> {dst_file}")
|
92
|
+
else:
|
93
|
+
# 如果dst包含文件名,则创建链接后重命名
|
94
|
+
dst_dir = os.path.dirname(dst)
|
95
|
+
os.makedirs(dst_dir, exist_ok=True)
|
96
|
+
# 只处理第一个匹配的文件
|
97
|
+
src_file = src_files[0]
|
98
|
+
dst_file = dst
|
99
|
+
if os.path.exists(dst_file):
|
100
|
+
os.remove(dst_file)
|
101
|
+
os.symlink(src_file, dst_file)
|
102
|
+
# print(f"创建符号链接并重命名: {src_file} -> {dst_file}")
|
103
|
+
print(f"Create a symbolic link and rename: {src_file} -> {dst_file}")
|
104
|
+
|
105
|
+
|
106
|
+
# ** 复制文件或目录,支持通配符
|
107
|
+
def copy_file(src_pattern, dst):
|
108
|
+
"""
|
109
|
+
# 描述:复制文件或目录,支持通配符
|
110
|
+
# 使用示例
|
111
|
+
# copy_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test/py.o')
|
112
|
+
# copy_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test')
|
113
|
+
param {*} src_pattern # 源文件或目录
|
114
|
+
param {*} dst # 目标文件或目录
|
115
|
+
"""
|
116
|
+
src_pattern = str(src_pattern)
|
117
|
+
# 使用glob.glob来处理可能包含通配符的src
|
118
|
+
src_files = glob.glob(src_pattern)
|
119
|
+
if not src_files:
|
120
|
+
raise FileNotFoundError("File does not exist: {}".format(src_pattern))
|
121
|
+
|
122
|
+
# 判断dst是路径还是包含文件名的路径
|
123
|
+
if os.path.isdir(dst):
|
124
|
+
# 如果dst是路径,则保持源文件的文件名
|
125
|
+
dst_dir = dst
|
126
|
+
for src_file in src_files:
|
127
|
+
src_file_basename = os.path.basename(src_file)
|
128
|
+
dst_file = os.path.join(dst_dir, src_file_basename)
|
129
|
+
if os.path.exists(dst_file):
|
130
|
+
if os.path.isdir(dst_file):
|
131
|
+
shutil.rmtree(dst_file)
|
132
|
+
else:
|
133
|
+
os.remove(dst_file)
|
134
|
+
if os.path.isdir(src_file):
|
135
|
+
shutil.copytree(src_file, dst_file, symlinks=True)
|
136
|
+
else:
|
137
|
+
shutil.copy2(src_file, dst_file)
|
138
|
+
print(f"Copy file or directory: {src_file} -> {dst_file}")
|
139
|
+
else:
|
140
|
+
# 如果dst包含文件名,则复制后重命名
|
141
|
+
dst_dir = os.path.dirname(dst)
|
142
|
+
os.makedirs(dst_dir, exist_ok=True)
|
143
|
+
# 只处理第一个匹配的文件
|
144
|
+
src_file = src_files[0]
|
145
|
+
dst_file = dst
|
146
|
+
if os.path.exists(dst_file):
|
147
|
+
if os.path.isdir(dst_file):
|
148
|
+
shutil.rmtree(dst_file)
|
149
|
+
else:
|
150
|
+
os.remove(dst_file)
|
151
|
+
if os.path.isdir(src_file):
|
152
|
+
shutil.copytree(src_file, dst_file, symlinks=True)
|
153
|
+
else:
|
154
|
+
shutil.copy2(src_file, dst_file)
|
155
|
+
print(f"Copy and rename file or directory: {src_file} -> {dst_file}")
|
156
|
+
|
157
|
+
|
158
|
+
# ** 重命名文件,支持通配符
|
159
|
+
def rename_file(directory, old_str, new_str):
|
160
|
+
"""
|
161
|
+
# 描述:重命名目录下的文件,支持通配符
|
162
|
+
# 使用示例
|
163
|
+
directory_path = r"E:\\windfarm\\CROCO_FILES"
|
164
|
+
old_str = "croco"
|
165
|
+
new_str = "roms"
|
166
|
+
rename_file(directory_path, old_str, new_str)
|
167
|
+
param {*} directory # 目录
|
168
|
+
param {*} old_str # 要替换的字符串
|
169
|
+
param {*} new_str # 新字符串
|
170
|
+
"""
|
171
|
+
# 获取目录下的所有文件
|
172
|
+
files = os.listdir(directory)
|
173
|
+
|
174
|
+
# 构建正则表达式以匹配要替换的字符串
|
175
|
+
pattern = re.compile(re.escape(old_str))
|
176
|
+
|
177
|
+
# 遍历目录下的文件
|
178
|
+
for filename in files:
|
179
|
+
# 检查文件名中是否包含要替换的字符串
|
180
|
+
if pattern.search(filename):
|
181
|
+
# 构建新的文件名
|
182
|
+
new_filename = pattern.sub(new_str, filename)
|
183
|
+
|
184
|
+
# 构建旧文件的完整路径
|
185
|
+
old_path = os.path.join(directory, filename)
|
186
|
+
|
187
|
+
# 构建新文件的完整路径
|
188
|
+
new_path = os.path.join(directory, new_filename)
|
189
|
+
|
190
|
+
# 重命名文件
|
191
|
+
os.rename(old_path, new_path)
|
192
|
+
print(f"Rename file: {old_path} -> {new_path}")
|
193
|
+
|
194
|
+
|
195
|
+
# ** 创建子文件夹(可选清空)
|
196
|
+
def make_folder(rootpath=None, folder_name=None, clear=False) -> str:
|
197
|
+
"""
|
198
|
+
# 描述:创建子文件夹(可选清空)
|
199
|
+
# 使用示例
|
200
|
+
rootpath = r'E:\\Data\\2024\\09\\17'
|
201
|
+
folder_name = 'var1'
|
202
|
+
newpath = make_folder(rootpath, folder_name, clear=1)
|
203
|
+
param {*} rootpath # 根目录
|
204
|
+
param {*} folder_name # 文件夹名称
|
205
|
+
"""
|
206
|
+
if rootpath is None:
|
207
|
+
rootpath = os.getcwd()
|
208
|
+
folder_path = os.path.join(str(rootpath), str(folder_name))
|
209
|
+
if clear:
|
210
|
+
shutil.rmtree(folder_path, ignore_errors=True)
|
211
|
+
os.makedirs(folder_path, exist_ok=True)
|
212
|
+
return folder_path
|
213
|
+
|
214
|
+
|
215
|
+
# ** 创建路径
|
216
|
+
def make_dir(directory):
|
217
|
+
"""
|
218
|
+
Description:
|
219
|
+
Create a directory if it does not exist
|
220
|
+
|
221
|
+
Parameters:
|
222
|
+
directory: The directory path to create
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
None
|
226
|
+
|
227
|
+
Example:
|
228
|
+
make_dir(r"E:\\Data\\2024\\09\\17\\var1")
|
229
|
+
"""
|
230
|
+
directory = str(directory)
|
231
|
+
if os.path.exists(directory):
|
232
|
+
print(f"Directory already exists: {directory}")
|
233
|
+
return
|
234
|
+
else:
|
235
|
+
os.makedirs(directory, exist_ok=True)
|
236
|
+
print(f"Created directory: {directory}")
|
237
|
+
|
238
|
+
|
239
|
+
# ** 清空文件夹
|
240
|
+
def clear_folder(folder_path):
|
241
|
+
"""
|
242
|
+
# 描述:清空文件夹
|
243
|
+
# 使用示例
|
244
|
+
clear_folder(r'E:\\Data\\2024\\09\\17\\var1')
|
245
|
+
param {*} folder_path # 文件夹路径
|
246
|
+
"""
|
247
|
+
folder_path = str(folder_path)
|
248
|
+
if os.path.exists(folder_path):
|
249
|
+
try:
|
250
|
+
# 遍历文件夹中的所有文件和子文件夹
|
251
|
+
for filename in os.listdir(folder_path):
|
252
|
+
file_path = os.path.join(folder_path, filename)
|
253
|
+
# 判断是文件还是文件夹
|
254
|
+
if os.path.isfile(file_path) or os.path.islink(file_path):
|
255
|
+
os.unlink(file_path) # 删除文件或链接
|
256
|
+
elif os.path.isdir(file_path):
|
257
|
+
shutil.rmtree(file_path) # 删除子文件夹
|
258
|
+
# print(f"成功清空文件夹: {folder_path}")
|
259
|
+
print(f"Successfully cleared the folder: {folder_path}")
|
260
|
+
except Exception as e:
|
261
|
+
# print(f"清空文件夹失败: {folder_path}")
|
262
|
+
print(f"Failed to clear the folder: {folder_path}")
|
263
|
+
print(e)
|
264
|
+
|
265
|
+
|
266
|
+
# ** 清理空文件夹
|
267
|
+
def remove_empty_folder(path, print_info=1):
|
268
|
+
"""
|
269
|
+
# 描述:清理空文件夹
|
270
|
+
# 使用示例
|
271
|
+
remove_empty_folder(r'E:\\Data\\2024\\09\\17', print_info=1)
|
272
|
+
param {*} path # 文件夹路径
|
273
|
+
param {*} print_info # 是否打印信息
|
274
|
+
"""
|
275
|
+
path = str(path)
|
276
|
+
# 遍历当前目录下的所有文件夹和文件
|
277
|
+
for root, dirs, files in os.walk(path, topdown=False):
|
278
|
+
# 遍历文件夹列表
|
279
|
+
for folder in dirs:
|
280
|
+
folder_path = os.path.join(root, folder)
|
281
|
+
# 判断文件是否有权限访问
|
282
|
+
try:
|
283
|
+
os.listdir(folder_path)
|
284
|
+
except OSError:
|
285
|
+
continue
|
286
|
+
# 判断文件夹是否为空
|
287
|
+
if not os.listdir(folder_path):
|
288
|
+
# 删除空文件夹
|
289
|
+
try:
|
290
|
+
os.rmdir(folder_path)
|
291
|
+
print(f"Deleted empty folder: {folder_path}")
|
292
|
+
except OSError:
|
293
|
+
if print_info:
|
294
|
+
print(f"Skipping protected folder: {folder_path}")
|
295
|
+
pass
|
296
|
+
|
297
|
+
|
298
|
+
# ** 删除相关文件,可使用通配符
|
299
|
+
def remove(pattern):
|
300
|
+
"""
|
301
|
+
Delete files or directories that match the given wildcard pattern.
|
302
|
+
|
303
|
+
Parameters:
|
304
|
+
pattern : str
|
305
|
+
File path or string containing wildcards. For example:
|
306
|
+
- r'E:\\Code\\Python\\Model\\WRF\\Radar2\\bzip2-radar-0*'
|
307
|
+
- 'bzip2-radar-0*' (assuming you are already in the target directory)
|
308
|
+
|
309
|
+
Usage examples:
|
310
|
+
remove(r'E:\\Code\\Python\\Model\\WRF\\Radar2\\bzip2-radar-0*')
|
311
|
+
or
|
312
|
+
os.chdir(r'E:\\Code\\Python\\Model\\WRF\\Radar2')
|
313
|
+
remove('bzip2-radar-0*')
|
314
|
+
|
315
|
+
last updated: 2025-01-10 11:49:13
|
316
|
+
"""
|
317
|
+
pattern = str(pattern)
|
318
|
+
|
319
|
+
# Use glob.glob to get all matching files or directories
|
320
|
+
file_list = glob.glob(pattern)
|
321
|
+
|
322
|
+
if not file_list:
|
323
|
+
print(f"No files or directories found matching '{pattern}'.")
|
324
|
+
return
|
325
|
+
|
326
|
+
for file_path in file_list:
|
327
|
+
if os.path.exists(file_path):
|
328
|
+
try:
|
329
|
+
if os.path.isdir(file_path):
|
330
|
+
shutil.rmtree(file_path)
|
331
|
+
print(f"Successfully deleted directory: {file_path}")
|
332
|
+
else:
|
333
|
+
os.remove(file_path)
|
334
|
+
print(f"Successfully deleted file: {file_path}")
|
335
|
+
except Exception as e:
|
336
|
+
print(f"Deletion failed: {file_path}")
|
337
|
+
print(f"Error message: {e}")
|
338
|
+
else:
|
339
|
+
print(f"File or directory does not exist: {file_path}")
|
340
|
+
|
341
|
+
|
342
|
+
# ** 获取文件大小
|
343
|
+
def file_size(file_path, unit="KB"):
|
344
|
+
"""
|
345
|
+
Description: 获取文件大小
|
346
|
+
|
347
|
+
Args:
|
348
|
+
file_path: 文件路径
|
349
|
+
unit: 单位(PB、TB、GB、MB、KB)
|
350
|
+
|
351
|
+
Returns:
|
352
|
+
文件大小(单位:PB、TB、GB、MB、KB)
|
353
|
+
"""
|
354
|
+
# 检查文件是否存在
|
355
|
+
if not os.path.exists(file_path):
|
356
|
+
# return "文件不存在"
|
357
|
+
# print(f"文件不存在: {file_path}\n返回0.0")
|
358
|
+
print(f'File does not exist: {file_path}\nReturn 0.0')
|
359
|
+
return 0.0
|
360
|
+
|
361
|
+
# 获取文件大小(字节)
|
362
|
+
file_size = os.path.getsize(file_path)
|
363
|
+
|
364
|
+
# 单位转换字典
|
365
|
+
unit_dict = {"PB": 1024**5, "TB": 1024**4, "GB": 1024**3, "MB": 1024**2, "KB": 1024}
|
366
|
+
|
367
|
+
# 检查传入的单位是否合法
|
368
|
+
if unit not in unit_dict:
|
369
|
+
# return "单位不合法,请选择PB、TB、GB、MB、KB中的一个"
|
370
|
+
# print("单位不合法,请选择PB、TB、GB、MB、KB中的一个\n返回0.0")
|
371
|
+
print("Invalid unit, please choose one of PB, TB, GB, MB, KB\nReturn 0.0")
|
372
|
+
return 0.0
|
373
|
+
|
374
|
+
# 转换文件大小到指定单位
|
375
|
+
converted_size = file_size / unit_dict[unit]
|
376
|
+
|
377
|
+
return converted_size
|
378
|
+
|
379
|
+
|
380
|
+
# ** 计算文件夹下指定相关文件的平均大小
|
381
|
+
def mean_size(parent_path,fname,max_num=None,unit="KB"):
|
382
|
+
"""
|
383
|
+
Description:
|
384
|
+
Calculate the average size of the specified related files in the folder
|
385
|
+
|
386
|
+
Parameters:
|
387
|
+
parent_path: The parent path where the files are located
|
388
|
+
fname: The file name pattern to search for
|
389
|
+
max_num: The maximum number of files to search for
|
390
|
+
unit: The unit of the file size, default is "KB"
|
391
|
+
|
392
|
+
Returns:
|
393
|
+
The average size
|
394
|
+
"""
|
395
|
+
flist = find_file(parent_path, fname)
|
396
|
+
if flist:
|
397
|
+
if max_num:
|
398
|
+
flist = flist[:int(max_num)]
|
399
|
+
size_list = [file_size(f,unit) for f in flist if file_size(f,unit) > 0]
|
400
|
+
if size_list:
|
401
|
+
return sum(size_list) / len(size_list)
|
402
|
+
else:
|
403
|
+
return 0.0
|
404
|
+
else:
|
405
|
+
return 0.0
|
406
|
+
|
407
|
+
|
408
|
+
if __name__ == "__main__":
|
409
|
+
# newpath = make_folder('D:/Data/2024/09/17/', 'var1', clear=1)
|
410
|
+
# print(newpath)
|
411
|
+
pass
|
412
|
+
|
413
|
+
remove(r"I:\\Delete\\test\\*")
|
oafuncs/oa_help.py
ADDED
@@ -0,0 +1,144 @@
|
|
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: 2025-01-01 21:09:58
|
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.12
|
14
|
+
"""
|
15
|
+
|
16
|
+
import oafuncs
|
17
|
+
import pkgutil
|
18
|
+
import importlib
|
19
|
+
from rich import print
|
20
|
+
|
21
|
+
__all__ = ["query", "use", "log"]
|
22
|
+
|
23
|
+
|
24
|
+
def query():
|
25
|
+
"""
|
26
|
+
Description:
|
27
|
+
Show the number of functions and the list of functions in the module.
|
28
|
+
Example:
|
29
|
+
query()
|
30
|
+
"""
|
31
|
+
funcs = [func for func in dir(oafuncs) if callable(getattr(oafuncs, func))]
|
32
|
+
print("函数数量:")
|
33
|
+
print(len(funcs))
|
34
|
+
print("函数列表:")
|
35
|
+
print(funcs)
|
36
|
+
|
37
|
+
# 判断同名函数个数
|
38
|
+
func_dict = dict()
|
39
|
+
for func in funcs:
|
40
|
+
func_dict[func] = 0
|
41
|
+
for module_info in pkgutil.iter_modules(oafuncs.__path__, oafuncs.__name__ + "."):
|
42
|
+
module = importlib.import_module(module_info.name)
|
43
|
+
for func in funcs:
|
44
|
+
if hasattr(module, func):
|
45
|
+
func_dict[func] += 1
|
46
|
+
print("同名函数:")
|
47
|
+
for func, count in func_dict.items():
|
48
|
+
if count > 1:
|
49
|
+
print(f"{func} : {count}")
|
50
|
+
|
51
|
+
|
52
|
+
def _use_single(func="get_var", module="oafuncs"):
|
53
|
+
"""
|
54
|
+
description: 查看函数的模块全路径和函数提示
|
55
|
+
param {func} : 函数名
|
56
|
+
example: use('get_var')
|
57
|
+
"""
|
58
|
+
module = importlib.import_module(module)
|
59
|
+
print("模块全路径:")
|
60
|
+
print(getattr(module, func).__module__ + "." + func)
|
61
|
+
print("函数提示:")
|
62
|
+
print(getattr(module, func).__doc__)
|
63
|
+
|
64
|
+
|
65
|
+
def use(func_name='log'):
|
66
|
+
"""
|
67
|
+
Description:
|
68
|
+
Show the full path and help of the function.
|
69
|
+
Args:
|
70
|
+
func_name: The name of the function.
|
71
|
+
Example:
|
72
|
+
use('log')
|
73
|
+
"""
|
74
|
+
found = False
|
75
|
+
# 假设oafuncs是一个包
|
76
|
+
if hasattr(oafuncs, "__path__"):
|
77
|
+
print("-" * 40) # 分隔线
|
78
|
+
# 遍历包内的所有模块
|
79
|
+
for module_info in pkgutil.iter_modules(oafuncs.__path__, oafuncs.__name__ + "."):
|
80
|
+
module_name = module_info.name
|
81
|
+
module = importlib.import_module(module_name)
|
82
|
+
if hasattr(module, func_name):
|
83
|
+
found = True
|
84
|
+
func_obj = getattr(module, func_name)
|
85
|
+
print(f"[bold purple]模块全路径:\n[bold green]{func_obj.__module__}.{func_name}\n")
|
86
|
+
help(func_obj)
|
87
|
+
""" doc = func_obj.__doc__
|
88
|
+
print("函数提示:")
|
89
|
+
if doc:
|
90
|
+
print(doc)
|
91
|
+
else:
|
92
|
+
print("无文档字符串") """
|
93
|
+
print("-" * 40) # 分隔线
|
94
|
+
else:
|
95
|
+
# 如果oafuncs只是一个模块,直接查找
|
96
|
+
if hasattr(oafuncs, func_name):
|
97
|
+
found = True
|
98
|
+
func_obj = getattr(oafuncs, func_name)
|
99
|
+
print(f"模块全路径:\n{func_obj.__module__}.{func_name}\n")
|
100
|
+
help(func_obj)
|
101
|
+
""" doc = func_obj.__doc__
|
102
|
+
print("函数提示:")
|
103
|
+
if doc:
|
104
|
+
print(doc)
|
105
|
+
else:
|
106
|
+
print("无文档字符串") """
|
107
|
+
if not found:
|
108
|
+
print(f"在oafuncs中没有找到名为 '{func_name}' 的函数。")
|
109
|
+
|
110
|
+
|
111
|
+
def log():
|
112
|
+
"""
|
113
|
+
Description:
|
114
|
+
Show the update log.
|
115
|
+
Example:
|
116
|
+
log()
|
117
|
+
"""
|
118
|
+
print("更新日志:")
|
119
|
+
print(
|
120
|
+
"""
|
121
|
+
2025-01-15
|
122
|
+
1. 优化了doi下载文献函数,增加下载途径及优化异常处理
|
123
|
+
"""
|
124
|
+
)
|
125
|
+
print(
|
126
|
+
"""
|
127
|
+
2025-01-07
|
128
|
+
1. 测试Python版本最低为3.9
|
129
|
+
2. 优化了部分函数说明
|
130
|
+
3. 优化hycom_3hourly模块,滑动判断文件是否正常
|
131
|
+
"""
|
132
|
+
)
|
133
|
+
print(
|
134
|
+
"""
|
135
|
+
2025-01-01
|
136
|
+
1. 添加了log函数,可以查看更新日志。
|
137
|
+
2. 修改部分函数名,尽可能简化函数名。
|
138
|
+
"""
|
139
|
+
)
|
140
|
+
|
141
|
+
|
142
|
+
if __name__ == "__main__":
|
143
|
+
# use("find_file")
|
144
|
+
query()
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# coding=utf-8
|
3
|
+
"""
|
4
|
+
Author: Liu Kun && 16031215@qq.com
|
5
|
+
Date: 2025-03-09 16:28:42
|
6
|
+
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
+
LastEditTime: 2025-03-09 16:28:42
|
8
|
+
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_model\\__init__.py
|
9
|
+
Description:
|
10
|
+
EditPlatform: vscode
|
11
|
+
ComputerInfo: XPS 15 9510
|
12
|
+
SystemInfo: Windows 11
|
13
|
+
Python Version: 3.12
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
# 会导致OAFuncs直接导入所有函数,不符合模块化设计
|
18
|
+
from .roms import *
|
19
|
+
from .wrf import *
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# coding=utf-8
|
3
|
+
"""
|
4
|
+
Author: Liu Kun && 16031215@qq.com
|
5
|
+
Date: 2025-03-09 16:30:02
|
6
|
+
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
+
LastEditTime: 2025-03-09 18:23:30
|
8
|
+
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_model\\roms\\__init__.py
|
9
|
+
Description:
|
10
|
+
EditPlatform: vscode
|
11
|
+
ComputerInfo: XPS 15 9510
|
12
|
+
SystemInfo: Windows 11
|
13
|
+
Python Version: 3.12
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
# 会导致OAFuncs直接导入所有函数,不符合模块化设计
|
20
|
+
from .test import *
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# coding=utf-8
|
3
|
+
"""
|
4
|
+
Author: Liu Kun && 16031215@qq.com
|
5
|
+
Date: 2025-03-09 16:30:54
|
6
|
+
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
+
LastEditTime: 2025-03-09 16:30:54
|
8
|
+
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_model\\roms\\depth.py
|
9
|
+
Description:
|
10
|
+
EditPlatform: vscode
|
11
|
+
ComputerInfo: XPS 15 9510
|
12
|
+
SystemInfo: Windows 11
|
13
|
+
Python Version: 3.12
|
14
|
+
"""
|
15
|
+
|
16
|
+
__all__ = ['test']
|
17
|
+
|
18
|
+
def test():
|
19
|
+
print('test')
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# coding=utf-8
|
3
|
+
"""
|
4
|
+
Author: Liu Kun && 16031215@qq.com
|
5
|
+
Date: 2025-03-09 16:29:59
|
6
|
+
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
+
LastEditTime: 2025-03-09 16:29:59
|
8
|
+
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_model\\wrf\\__init__.py
|
9
|
+
Description:
|
10
|
+
EditPlatform: vscode
|
11
|
+
ComputerInfo: XPS 15 9510
|
12
|
+
SystemInfo: Windows 11
|
13
|
+
Python Version: 3.12
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
# 会导致OAFuncs直接导入所有函数,不符合模块化设计
|
18
|
+
from .little_r import *
|