funcguard 0.2.14__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 tinycen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,686 @@
1
+ Metadata-Version: 2.4
2
+ Name: funcguard
3
+ Version: 0.2.14
4
+ Summary: FuncGuard是一个Python库,提供函数执行超时控制、重试机制、HTTP请求封装和格式化打印工具。
5
+ Home-page: https://github.com/tinycen/funcguard
6
+ Author: tinycen
7
+ Author-email: sky_ruocen@qq.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: requests
15
+ Requires-Dist: pandas
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: classifier
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: license-file
23
+ Dynamic: requires-dist
24
+ Dynamic: requires-python
25
+ Dynamic: summary
26
+
27
+ # FuncGuard
28
+
29
+ FuncGuard是一个Python库,提供了函数执行超时控制和重试机制的实用工具。
30
+ [![zread](icon/zread-badge.svg)](https://zread.ai/tinycen/funcguard)
31
+
32
+ ## 功能特点
33
+
34
+ - 函数执行超时控制
35
+ - 函数执行失败自动重试
36
+ - HTTP请求封装(支持自动重试)
37
+ - 格式化打印工具(分隔线和块打印)
38
+ - 进度条显示功能
39
+ - 时间日志记录和耗时统计
40
+ - 函数执行时间监控和警告
41
+ - IP地址检测(局域网IP和公网IP)
42
+ - 时间等待功能(带倒计时显示)
43
+ - pandas数据处理工具(空值填充、列类型转换、Decimal转换、JSON字符串转换等)
44
+ - 数值差异格式化工具(格式化数值变化,如+5、-3等)
45
+
46
+ ## 安装/升级
47
+
48
+ ```bash
49
+ pip install --upgrade funcguard
50
+ ```
51
+
52
+
53
+ ## 使用方法
54
+
55
+ ### 超时控制
56
+
57
+ 使用`timeout_handler`函数可以控制函数的执行时间,防止函数运行时间过长:
58
+
59
+ ```python
60
+ from funcguard import timeout_handler
61
+
62
+ def long_running_function():
63
+ # 模拟一个耗时操作
64
+ import time
65
+ time.sleep(10)
66
+ return "操作完成"
67
+
68
+ try:
69
+ # 设置超时时间为5秒
70
+ result = timeout_handler(long_running_function, execution_timeout=5)
71
+ print(result)
72
+ except TimeoutError as e:
73
+ print(f"捕获到超时错误: {e}")
74
+ ```
75
+
76
+ ### 重试机制
77
+
78
+ 使用`retry_function`函数可以在函数执行失败时自动重试:
79
+
80
+ ```python
81
+ from funcguard import retry_function
82
+
83
+ def unstable_function():
84
+ # 模拟一个可能失败的操作
85
+ import random
86
+ if random.random() < 0.7: # 70%的概率失败
87
+ raise Exception("随机错误")
88
+ return "操作成功"
89
+
90
+ try:
91
+ # 最多重试3次,每次执行超时时间为10秒
92
+ result = retry_function(unstable_function, max_retries=3, execute_timeout=10, task_name="测试任务")
93
+ print(result)
94
+ except Exception as e:
95
+ print(f"重试后仍然失败: {e}")
96
+ ```
97
+
98
+ ### HTTP请求
99
+
100
+ 使用`send_request`函数发送HTTP请求,支持自动重试:
101
+
102
+ ```python
103
+ from funcguard import send_request
104
+
105
+ # 不使用重试
106
+ response = send_request(
107
+ method="GET",
108
+ url="https://api.example.com/data",
109
+ headers={"Content-Type": "application/json"},
110
+ timeout=30
111
+ )
112
+ print(response)
113
+
114
+ # 使用重试
115
+ response = send_request(
116
+ method="POST",
117
+ url="https://api.example.com/data",
118
+ headers={"Content-Type": "application/json"},
119
+ data={"key": "value"},
120
+ timeout=30,
121
+ auto_retry={
122
+ "task_name": "API请求",
123
+ "max_retries": 3,
124
+ "execute_timeout": 60
125
+ }
126
+ )
127
+ print(response)
128
+ ```
129
+
130
+ ### 格式化打印
131
+
132
+ 使用`print_line`、`print_block`、`print_title`和`print_progress`函数进行格式化打印,便于查看和调试:
133
+
134
+ ```python
135
+ from funcguard import print_line, print_block, print_title, print_progress
136
+
137
+ # 打印带等号的标题
138
+ print_title("初始化分类器") # 输出:=== 初始化分类器 ===
139
+ print_title("训练完成", separator_char="*", padding_length=2) # 输出:** 训练完成 **
140
+
141
+ # 打印分隔线
142
+ print_line() # 默认使用40个'-'字符
143
+ print_line("*", 30) # 使用30个'*'字符
144
+
145
+ # 打印块内容
146
+ print_block("用户信息", {"name": "张三", "age": 25})
147
+
148
+ # 自定义分隔符
149
+ print_block("配置信息", {"debug": True, "port": 8080}, "=", 50)
150
+
151
+ # 打印复杂内容
152
+ result = {
153
+ "status": "success",
154
+ "data": [1, 2, 3, 4, 5],
155
+ "message": "操作完成"
156
+ }
157
+ print_block("API响应", result)
158
+
159
+ # 打印进度条
160
+ for i in range(101):
161
+ import time
162
+ time.sleep(0.05) # 模拟处理时间
163
+ print_progress(i, 100, "处理中") # 显示进度条和处理状态
164
+ print() # 处理完成后换行
165
+ ```
166
+
167
+ ### 时间日志记录
168
+
169
+ - 自动显示北京时间(UTC+8)
170
+ - 支持进度显示和预计完成时间计算
171
+ - 提供中英文双语统计信息
172
+ - 可显示总耗时、平均耗时等详细统计
173
+ - 支持i从0或从1开始的计数方式
174
+ - 支持函数执行时间监控和警告
175
+
176
+ 使用`time_log`和`time_diff`函数记录任务执行时间和统计信息:
177
+
178
+ ```python
179
+ from funcguard import time_log, time_diff
180
+
181
+ # 获取开始时间
182
+ start_time = time_diff()
183
+
184
+ # 记录任务开始(i从0开始)
185
+ time_log("开始处理数据", 0, 100, start_time, 0)
186
+
187
+ # 模拟处理过程
188
+ import time
189
+ for i in range(1, 101):
190
+ time.sleep(0.1) # 模拟处理时间
191
+ if i % 20 == 0:
192
+ time_log(f"处理进度", i, 100, start_time, 0) # 显示进度和预计完成时间
193
+
194
+ # 记录任务完成并打印统计信息
195
+ time_diff(start_time, 100, "cn") # 中文显示统计信息
196
+ ```
197
+
198
+ 或者当i从1开始时:
199
+
200
+ ```python
201
+ # 记录任务开始(i从1开始)
202
+ time_log("开始处理数据", 1, 100, start_time, 1)
203
+
204
+ # 模拟处理过程
205
+ import time
206
+ for i in range(1, 101):
207
+ time.sleep(0.1) # 模拟处理时间
208
+ if i % 20 == 0:
209
+ time_log(f"处理进度", i, 100, start_time, 1) # 显示进度和预计完成时间
210
+
211
+ ```
212
+
213
+ ### 组合示例用法
214
+
215
+ 在实际应用中,可以组合使用`time_log`和`print_progress`来显示处理进度和剩余时间:
216
+
217
+ ```python
218
+ from funcguard import time_diff, time_log, print_progress
219
+ import pandas as pd
220
+
221
+ def process_images(images):
222
+ """处理图片的示例函数"""
223
+ # 模拟图片处理
224
+ import time
225
+ time.sleep(0.1)
226
+ return f"processed_{images}"
227
+
228
+ # 假设df是一个包含图片数据的DataFrame
229
+ df = pd.DataFrame({"images": [f"img_{i}.jpg" for i in range(100)]})
230
+
231
+ # 获取开始时间
232
+ s_time = time_diff()
233
+ processed_images_list = []
234
+ max_num = len(df)
235
+
236
+ # 处理每一行数据
237
+ for index, row in df.iterrows():
238
+ processed_images_list.append(process_images(row["images"]))
239
+
240
+ # 获取剩余时间并显示进度条
241
+ remaining_time = time_log("", index, max_num, s_time, return_field="remaining_time")
242
+ print_progress(index, max_num, remaining_time)
243
+
244
+ # 更新DataFrame中的图片数据
245
+ df["images"] = processed_images_list
246
+
247
+ # 打印处理完成后的统计信息
248
+ time_diff(s_time, max_num)
249
+ ```
250
+
251
+ 这个组合示例展示了如何:
252
+ 1. 使用`time_diff()`获取开始时间
253
+ 2. 在循环中使用`time_log`获取剩余时间(通过`return_field="remaining_time"`参数)
254
+ 3. 使用`print_progress`显示进度条和剩余时间
255
+ 4. 最后使用`time_diff`打印完整的处理统计信息
256
+
257
+ ### 时间等待
258
+
259
+ 使用`time_wait`函数进行带倒计时显示的时间等待:
260
+
261
+ ```python
262
+ from funcguard import time_wait
263
+
264
+ # 等待10秒,显示倒计时
265
+ print("开始等待...")
266
+ time_wait(10) # 显示倒计时:Time wait: 10s, 9s, 8s...
267
+ print("等待完成!")
268
+
269
+ # 等待5秒
270
+ print("准备开始下一步操作...")
271
+ time_wait(5)
272
+ print("开始执行下一步操作")
273
+ ```
274
+
275
+ ### 执行时间监控
276
+
277
+ 使用`time_monitor`函数监控函数执行时间:
278
+
279
+ ```python
280
+ from funcguard import time_monitor
281
+
282
+ def some_function():
283
+ # 模拟一个耗时操作
284
+ import time
285
+ time.sleep(2)
286
+ return "操作完成"
287
+
288
+ # 模式1:总是打印执行时间
289
+ result = time_monitor(
290
+ func=some_function,
291
+ print_mode=1
292
+ )
293
+ print(f"结果: {result}")
294
+
295
+ # 模式2:仅在超过阈值时打印警告
296
+ result = time_monitor(
297
+ func=some_function,
298
+ warning_threshold=1.5, # 设置1.5秒的警告阈值
299
+ print_mode=2
300
+ )
301
+ print(f"结果: {result}")
302
+
303
+ # 模式0:不打印任何信息,仅返回结果和执行时间
304
+ result, duration = time_monitor(
305
+ func=some_function,
306
+ print_mode=0
307
+ )
308
+ print(f"结果: {result}, 耗时: {duration}秒")
309
+ ```
310
+
311
+ ### IP地址检测
312
+
313
+ 使用IP检测功能获取本机局域网IP、公网IP以及验证IP地址格式:
314
+
315
+ ```python
316
+ from funcguard import get_local_ip, get_public_ip, get_ip_info, is_valid_ip
317
+
318
+ # 获取本机局域网IP地址
319
+ local_ip = get_local_ip()
320
+ print(f"本机局域网IP: {local_ip}")
321
+
322
+ # 获取本机公网IP地址
323
+ public_ip = get_public_ip()
324
+ print(f"本机公网IP: {public_ip}")
325
+
326
+ # 获取完整的IP信息(包括局域网IP、公网IP和主机名)
327
+ ip_info = get_ip_info()
328
+ print(f"主机名: {ip_info['hostname']}")
329
+ print(f"局域网IP: {ip_info['local_ip']}")
330
+ print(f"公网IP: {ip_info['public_ip']}")
331
+
332
+ # 验证IP地址格式是否有效
333
+ test_ips = ["192.168.1.1", "256.1.1.1", "abc.def.ghi.jkl"]
334
+ for ip in test_ips:
335
+ is_valid = is_valid_ip(ip)
336
+ print(f"IP地址 '{ip}' 验证结果: {is_valid}")
337
+ ```
338
+
339
+ ### pandas数据处理工具
340
+
341
+ 使用pandas工具进行数据处理和类型转换:
342
+
343
+ ```python
344
+ import pandas as pd
345
+ from funcguard import pd_fill_null, pd_round_columns, pd_convert_columns, pd_convert_decimal
346
+ from decimal import Decimal
347
+
348
+ # 创建示例DataFrame
349
+ df = pd.DataFrame({
350
+ 'name': ['张三', '李四', None, '王五'],
351
+ 'age': [25.7, 30.2, 28.9, 35.1],
352
+ 'salary': [Decimal('5000.50'), Decimal('6000.75'), Decimal('5500.25'), Decimal('7000.00')],
353
+ 'score': [85.678, 92.345, 78.901, 88.234],
354
+ 'join_date': ['2023-01-15', '2023-02-20', '2023-03-10', '2023-04-05']
355
+ })
356
+
357
+ # 1. 填充空值
358
+ df = pd_fill_null(df, {'name': '未知'}, None) # 将name列的空值填充为'未知'
359
+
360
+ # 2. 四舍五入指定列
361
+ df = pd_round_columns(df, ['age'], 0) # 将age列四舍五入到整数
362
+
363
+ # 3. 转换列数据类型
364
+ df = pd_convert_columns(df, {
365
+ 'age': 'int',
366
+ 'join_date': 'datetime',
367
+ 'name': 'str'
368
+ })
369
+
370
+ # 4. 转换Decimal类型
371
+ df = pd_convert_decimal(df, ['salary'], 'float') # 将salary列的Decimal转换为float
372
+
373
+ # 5. 批量处理多个列
374
+ df = pd_fill_null(df, ['score'], 0) # 将score列的空值填充为0
375
+ df = pd_round_columns(df, ['score'], 1) # 将score列四舍五入到1位小数
376
+
377
+ print(df)
378
+ print(df.dtypes)
379
+ ```
380
+
381
+ ### JSON字符串转换
382
+
383
+ 使用`pd_load_json`函数将DataFrame中的JSON字符串列转换为Python对象:
384
+
385
+ ```python
386
+ import pandas as pd
387
+ from funcguard import pd_load_json
388
+
389
+ # 创建包含JSON字符串的示例DataFrame
390
+ df = pd.DataFrame({
391
+ 'id': [1, 2, 3],
392
+ 'config': ['{"timeout": 30, "retry": 3}', '{"timeout": 60, "retry": 5}', ''],
393
+ 'metadata': ['{"version": "1.0", "env": "prod"}', '', '{"version": "2.0", "env": "dev"}']
394
+ })
395
+
396
+ # 将JSON字符串列转换为Python对象
397
+ df = pd_load_json(df, ['config', 'metadata'])
398
+
399
+ # 现在可以直接访问转换后的对象
400
+ print(df['config'][0]['timeout']) # 输出: 30
401
+ print(df['metadata'][2]['version']) # 输出: 2.0
402
+
403
+ # 处理空字符串(默认转换为{})
404
+ print(df['config'][2]) # 输出: {}
405
+ print(df['metadata'][1]) # 输出: {}
406
+ ```
407
+
408
+ ### 数值差异格式化
409
+
410
+ 使用`format_difference`函数格式化两个数值之间的差异,常用于显示数值变化:
411
+
412
+ ```python
413
+ from funcguard import format_difference
414
+
415
+ # 计算并格式化数值变化
416
+ old_value = 100
417
+ new_value = 150
418
+ print(format_difference(old_value, new_value)) # 输出: +50
419
+
420
+ old_value = 200
421
+ new_value = 180
422
+ print(format_difference(old_value, new_value)) # 输出: -20
423
+
424
+ old_value = 100
425
+ new_value = 100
426
+ print(format_difference(old_value, new_value)) # 输出: (空字符串)
427
+
428
+ # 在实际应用中的示例
429
+ current_price = 150.5
430
+ previous_price = 145.2
431
+ price_change = format_difference(previous_price, current_price)
432
+ print(f"当前价格: {current_price}, 变化: {price_change}") # 输出: 当前价格: 150.5, 变化: +5.3
433
+ ```
434
+
435
+
436
+ ## API文档
437
+
438
+ ### funcguard.core
439
+
440
+ #### timeout_handler(func, args=(), kwargs=None, execution_timeout=90)
441
+
442
+ - **参数**:
443
+ - `func`: 需要执行的目标函数
444
+ - `args`: 目标函数的位置参数,默认为空元组
445
+ - `kwargs`: 目标函数的关键字参数,默认为None
446
+ - `execution_timeout`: 函数执行的超时时间,单位为秒,默认为90秒
447
+ - **返回值**: 目标函数的返回值
448
+ - **异常**: `TimeoutError` - 当函数执行超过指定时间时抛出
449
+
450
+ #### retry_function(func, max_retries=5, execute_timeout=90, task_name="", *args, **kwargs)
451
+
452
+ - **参数**:
453
+ - `func`: 需要重试的函数
454
+ - `max_retries`: 最大重试次数,默认为5
455
+ - `execute_timeout`: 执行超时时间,默认为90秒
456
+ - `task_name`: 任务名称,用于打印日志
457
+ - `args`: func的位置参数
458
+ - `kwargs`: func的关键字参数
459
+ - **返回值**: func的返回值
460
+ - **异常**: 当重试次数用尽后仍然失败时,抛出最后一次的异常
461
+
462
+
463
+ ### funcguard.tools
464
+
465
+ #### encode_basic_auth(username, password)
466
+
467
+ - **参数**:
468
+ - `username`: 用户名字符串
469
+ - `password`: 密码字符串
470
+ - **返回值**: 用于HTTP Basic认证的Authorization头部字符串,格式为`Basic xxxxx`(base64编码)
471
+ - **功能**: 生成符合HTTP Basic认证要求的Authorization头部内容,常用于需要用户名和密码认证的HTTP请求。
472
+
473
+ #### send_request(method, url, headers=None, data=None, return_type="json", timeout=60, auto_retry=None)
474
+
475
+ - **参数**:
476
+ - `method`: HTTP方法(GET, POST等)
477
+ - `url`: 请求URL
478
+ - `headers`: 请求头,默认为None。若未传入且`data`为非空dict,则自动添加`Content-Type: application/json`。
479
+ - `data`: 请求数据,默认为None。支持dict、list、str等类型。若为dict或list会自动转为JSON字符串。
480
+ - `return_type`: 返回类型,可选"json"、"response"或"text",默认为"json"
481
+ - `timeout`: 请求超时时间,单位为秒,默认为60
482
+ - `auto_retry`: 自动重试配置,格式为`{"task_name": "", "max_retries": 5, "execute_timeout": 90}`,默认为None
483
+ - **返回值**: 根据return_type参数返回不同格式的响应数据
484
+ - **异常**: 当请求失败且重试次数用尽后,抛出相应的异常
485
+ - **注意**:
486
+ - 当`headers`为None且`data`为非空dict时,会自动设置`Content-Type: application/json`。
487
+ - 若已传入`headers`且未包含`Content-Type`,且`data`为非空dict,也会自动补充`Content-Type: application/json`。
488
+ - `data`为list类型时不会自动补充`Content-Type: application/json`,如需请自行传入headers。
489
+ - 其他类型的`data`(如str、bytes)将直接作为请求体发送。
490
+
491
+ ### funcguard.time_utils
492
+
493
+ #### time_log(message, i=0, max_num=0, s_time=None, start_from=0, return_field="progress_info")
494
+
495
+ - **参数**:
496
+ - `message`: 日志消息
497
+ - `i`: 当前进度,默认为0
498
+ - `max_num`: 总进度数量,默认为0
499
+ - `s_time`: 开始时间,用于计算预计完成时间,默认为None
500
+ - `start_from`: i是否从0开始,0表示从0开始,1表示从1开始,默认为0
501
+ - `return_field`: 返回字段,支持以下:
502
+ - "progress_info" 表示完整进度信息(默认)
503
+ - "remaining_time" 表示剩余时间
504
+ - "end_time" 表示预计完成时间
505
+ - **返回值**:
506
+ - 根据return_field参数返回不同的信息
507
+ - 默认情况下打印带时间戳的日志信息并返回进度信息
508
+ - **功能**: 打印带时间戳的日志信息,支持进度显示和预计完成时间计算
509
+
510
+ #### time_diff(s_time=None, max_num=0, language="cn", return_duration=1)
511
+
512
+ - **参数**:
513
+ - `s_time`: 开始时间,默认为None
514
+ - `max_num`: 任务数量,默认为0
515
+ - `language`: 语言选择("cn"中文,其他为英文),默认为"cn"
516
+ - `return_duration`: 返回模式,默认为1:
517
+ - 0 - 仅返回 total_seconds,不打印信息
518
+ - 1 - 仅打印信息,不返回 total_seconds
519
+ - 2 - 打印信息,并返回 total_seconds
520
+ - **返回值**:
521
+ - 如果s_time为None则返回当前时间
522
+ - 如果return_duration为0或2则返回持续时间(秒)
523
+ - 否则返回None
524
+ - **功能**: 计算并打印任务执行时间统计信息,支持中英文双语输出
525
+
526
+ #### time_monitor(warning_threshold=None, print_mode=2, func=None, *args, **kwargs)
527
+
528
+ - **参数**:
529
+ - `warning_threshold`: 警告阈值(秒),如果执行耗时超过此值则打印警告,默认为None
530
+ - `print_mode`: 打印模式,支持三种模式:
531
+ - 0 - 仅返回total_seconds,不打印任何信息
532
+ - 1 - 总是打印执行时间
533
+ - 2 - 仅在超时打印警告信息(默认)
534
+ - `func`: 要监控的函数
535
+ - `args`: 函数的位置参数
536
+ - `kwargs`: 函数的关键字参数
537
+ - **返回值**:
538
+ - print_mode == 0: 元组 (result, total_seconds) - 函数的执行结果和执行时间(秒)
539
+ - print_mode == 1: 函数的执行结果
540
+ - print_mode == 2: 函数的执行结果
541
+ - **功能**: 监控函数执行时间,并返回函数的执行结果和执行时间
542
+ - **注意**: 该方法内部使用 time_diff 函数,根据 print_mode 自动设置 return_duration 参数
543
+ - print_mode 为 0 或 2 时,设置 return_duration=0( time_diff 仅返回total_seconds,不打印信息)
544
+ - print_mode 为 1 时,设置 return_duration=2( time_diff 打印信息,并返回total_seconds)
545
+
546
+ #### time_wait(seconds: int = 10)
547
+
548
+ - **参数**:
549
+ - `seconds`: 等待的秒数,默认值为10秒
550
+ - **返回值**: 无
551
+ - **功能**: 等待指定的秒数,显示倒计时
552
+
553
+ ### funcguard.ip_utils
554
+
555
+ #### get_local_ip()
556
+
557
+ - **参数**: 无
558
+ - **返回值**: 本机局域网IP地址字符串,如果获取失败返回None
559
+ - **功能**: 获取本机局域网IP地址,通过创建UDP socket连接外部地址来获取本机IP
560
+
561
+ #### get_public_ip()
562
+
563
+ - **参数**: 无
564
+ - **返回值**: 公网IP地址字符串,如果获取失败返回None
565
+ - **功能**: 获取本机公网IP地址,使用多个IP查询服务作为备选(ipify.org、ipapi.co、ifconfig.me等),自动验证返回的IP地址格式
566
+
567
+ #### is_valid_ip(ip_string)
568
+
569
+ - **参数**:
570
+ - `ip_string`: 要验证的IP地址字符串
571
+ - **返回值**: 如果是有效的IP地址返回True,否则返回False
572
+ - **功能**: 验证字符串是否为有效的IP地址,检查IP地址格式(4个部分,每部分0-255)
573
+
574
+ #### get_ip_info()
575
+
576
+ - **参数**: 无
577
+ - **返回值**: 包含IP信息的字典,格式为`{'local_ip': '...', 'public_ip': '...', 'hostname': '...'}`
578
+ - **功能**: 获取本机IP地址信息(包括局域网IP、公网IP和主机名)
579
+
580
+ ### funcguard.printer
581
+
582
+ #### print_line(separator_char: str = "-", separator_length: int = 40) -> None
583
+
584
+ - **参数**:
585
+ - `separator_char`: 分隔符字符,默认为'-'
586
+ - `separator_length`: 分隔符长度,默认为40
587
+ - **返回值**: 无
588
+ - **功能**: 打印分隔线,用于分隔不同的打印块
589
+
590
+ #### print_title(title: str, separator_char: str = "=", padding_length: int = 3) -> None
591
+
592
+ - **参数**:
593
+ - `title`: 标题内容
594
+ - `separator_char`: 分隔符字符,默认为'='
595
+ - `padding_length`: 标题两侧的分隔符数量,默认为3
596
+ - **返回值**: 无
597
+ - **功能**: 打印带分隔符的标题,格式如:=== 初始化分类器 ===
598
+
599
+ #### print_block(title: str, content: Any, separator_char: str = "-", separator_length: int = 40) -> None
600
+
601
+ - **参数**:
602
+ - `title`: 标题
603
+ - `content`: 打印的内容
604
+ - `separator_char`: 分隔符字符,默认为'-'
605
+ - `separator_length`: 分隔符长度,默认为40
606
+ - **返回值**: 无
607
+ - **功能**: 使用分隔符打印标题和内容,便于查看
608
+
609
+ #### print_progress(idx: int, total: int, message: str = "") -> None
610
+
611
+ - **参数**:
612
+ - `idx`: 当前索引(从0开始)
613
+ - `total`: 总数量
614
+ - `message`: 额外消息,默认为空字符串
615
+ - **返回值**: 无
616
+ - **功能**: 打印进度条,显示当前进度,设计原理:
617
+ - 进度条总长度固定为50个字符,这是终端显示的最佳长度
618
+ - 使用整除2(//2)将0-100%映射到0-50字符,确保平滑过渡
619
+ - 已完成部分用'█'表示,未完成部分用'-'表示
620
+ - 使用\r回到行首覆盖之前的内容,保持在同一行更新
621
+
622
+ ### funcguard.pd_utils
623
+
624
+ #### pd_fill_null(df, columns, fill_value)
625
+
626
+ - **参数**:
627
+ - `df`: pandas DataFrame
628
+ - `columns`: 要填充的列,可以是List[str]或Dict[str, Any]。为列表时,所有列使用相同的fill_value;为字典时,键为列名,值为对应的填充值
629
+ - `fill_value`: 填充值,当columns为列表时使用
630
+ - **返回值**: 填充后的DataFrame
631
+ - **功能**: 替换DataFrame中指定列的空值为指定值
632
+
633
+ #### pd_round_columns(df, columns, digits=0)
634
+
635
+ - **参数**:
636
+ - `df`: pandas DataFrame
637
+ - `columns`: 要进行四舍五入的列名列表
638
+ - `digits`: 保留的小数位数,默认为0
639
+ - **返回值**: 四舍五入后的DataFrame
640
+ - **功能**: 对DataFrame中指定列进行四舍五入操作
641
+
642
+ #### pd_convert_columns(df, columns)
643
+
644
+ - **参数**:
645
+ - `df`: pandas DataFrame
646
+ - `columns`: 要转换类型的字典,键为列名,值为目标数据类型。支持的数据类型:'int', 'float', 'str', 'bool', 'datetime'
647
+ - **返回值**: 列类型转换后的DataFrame
648
+ - **功能**: 转换DataFrame中指定列的数据类型
649
+
650
+ #### pd_convert_decimal(df, columns=None, default_type='int')
651
+
652
+ - **参数**:
653
+ - `df`: pandas DataFrame
654
+ - `columns`: 要处理的列,可以是None、List[str]或Dict[str, str]。为None时检测所有列;为列表时检测指定列并使用default_type转换;为字典时键为列名,值为目标类型('int'或'float')
655
+ - `default_type`: 默认转换类型,'int'或'float',默认为'int'
656
+ - **返回值**: 转换后的DataFrame
657
+ - **功能**: 检测DataFrame中是否包含Decimal类型的字段,如果包含则转换为指定的数据类型
658
+ - **注意**: 只有object类型的列才可能包含Decimal类型数据
659
+
660
+ #### pd_load_json(df, columns, empty_to_dict=True)
661
+
662
+ - **参数**:
663
+ - `df`: pandas DataFrame
664
+ - `columns`: 要转换的列名列表
665
+ - `empty_to_dict`: 是否将空字符串转换为{},默认为True
666
+ - **返回值**: JSON转换后的DataFrame
667
+ - **功能**: 对DataFrame中指定的列执行json.loads操作,将JSON字符串转换为Python对象
668
+
669
+
670
+ ### funcguard.calculate
671
+
672
+ #### format_difference(old_value: int | float, new_value: int | float) -> str
673
+
674
+ - **参数**:
675
+ - `old_value`: 旧值(整数或浮点数)
676
+ - `new_value`: 新值(整数或浮点数)
677
+ - **返回值**: 格式化的差异字符串
678
+ - 若差异为0,返回空字符串
679
+ - 若差异为正,返回"+差异值"格式
680
+ - 若差异为负,返回"-差异值"格式
681
+ - **功能**: 格式化两个数值之间的差异,常用于显示数值变化
682
+
683
+
684
+ ## 许可证
685
+
686
+ MIT License