speedy-utils 1.1.42__tar.gz → 1.1.44__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.
- speedy_utils-1.1.44/.github/prompts/improveParallelErrorHandling.prompt.md +64 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/PKG-INFO +158 -9
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/README.md +155 -7
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/pyproject.toml +3 -2
- speedy_utils-1.1.44/scripts/bug.py +34 -0
- speedy_utils-1.1.44/scripts/bug_simple.py +11 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/scripts/debug_import_time.py +80 -18
- speedy_utils-1.1.44/scripts/test.py +26 -0
- speedy_utils-1.1.44/scripts/test_both_backends.py +25 -0
- speedy_utils-1.1.44/scripts/test_error_handling.py +37 -0
- speedy_utils-1.1.44/scripts/test_locals.py +18 -0
- speedy_utils-1.1.44/scripts/test_ray_locals.py +10 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/__init__.py +7 -0
- speedy_utils-1.1.44/src/speedy_utils/multi_worker/process.py +1309 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/multi_worker/thread.py +202 -42
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/uv.lock +5247 -2937
- speedy_utils-1.1.42/src/speedy_utils/multi_worker/process.py +0 -699
- speedy_utils-1.1.42/test2.txt +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.githooks/pre-push +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/copilot-instructions.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/caching-utilities/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/caching-utilities/examples/caching_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/io-utilities/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/io-utilities/examples/io_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/llm-integration/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/llm-integration/examples/llm_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/multi-threading-processing/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/ray-distributed-computing/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/skill-creation/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/vision-utilities/SKILL.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/skills/vision-utilities/examples/vision_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.github/workflows/publish.yml +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.gitignore +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/.pre-commit-config.yaml +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/AGENTS.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/bumpversion.sh +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/debug_generate_response.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/debug_n_param.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/debug_n_structure.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/integration_test.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/test_decode_api.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/test_endpoints.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/test_generate.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/debug/test_generate_endpoint.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/docs/GENERATE_QUICKREF.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/docs/IMPLEMENTATION.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/docs/QUICKSTART.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/docs/TOKENIZATION.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/docs/TOKENIZATION_IMPLEMENTATION.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/docs/zero_copy_sharing.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/generate_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/llm_ray_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/pytorch_large_model.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/shared_kwargs_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/temperature_range_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/test_parallel_gpu.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/test_share_ray.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/tokenization_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/examples/vision_utils_example.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/experiments/exp1/dockerfile +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/experiments/exp1/run_in_docker.sh +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/experiments/exp1/test.png +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/experiments/test_read_image.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/notebooks/README.ipynb +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/notebooks/llm_utils/llm_as_a_judge.ipynb +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/notebooks/parallel_gpu_pool.ipynb +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/notebooks/ray_tutorial.ipynb +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/notebooks/test_multi_thread.ipynb +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/ruff.toml +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/scripts/deploy.sh +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/scripts/imports.sh +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/scripts/test_import_time_vision.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/scripts/test_ray_mp.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/setup.cfg +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/datasets_utils/convert_to_arrow.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/chat_format/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/chat_format/display.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/chat_format/transform.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/chat_format/utils.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/group_messages.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/llm_ray.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/async_lm/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/async_lm/_utils.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/async_lm/async_llm_task.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/async_lm/async_lm.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/async_lm/async_lm_base.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/async_lm/lm_specific.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/base_prompt_builder.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/llm.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/llm_signature.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/lm_base.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/mixins.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/openai_memoize.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/signature.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/lm/utils.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/scripts/README.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/scripts/fast_vllm.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/scripts/vllm_load_balancer.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/scripts/vllm_serve.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/vector_cache/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/vector_cache/cli.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/vector_cache/core.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/vector_cache/types.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/llm_utils/vector_cache/utils.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/__imports.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/clock.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/function_decorator.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/logger.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/notebook_utils.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/patcher.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/report_manager.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/utils_cache.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/utils_io.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/utils_misc.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/common/utils_print.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/multi_worker/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/multi_worker/dataset_ray.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/multi_worker/parallel_gpu_pool.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/multi_worker/progress.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/scripts/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/scripts/mpython.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/speedy_utils/scripts/openapi_client_codegen.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/vision_utils/README.md +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/vision_utils/__init__.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/vision_utils/io_utils.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/src/vision_utils/plot.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/test_s3.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/import_all.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/import_time_report.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/integration_test.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/llm_utils/test_llm_mixins.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/sample_objects.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_logger.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_logger_format.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_memoize_typing.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_mpython.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_multithread_error_trace.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_process.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_process_update.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_pytorch_sharing.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_shared_kwargs.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_thread.py +0 -0
- {speedy_utils-1.1.42 → speedy_utils-1.1.44}/tests/test_tokenization.py +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: improveParallelErrorHandling
|
|
3
|
+
description: Enhance error tracebacks in parallel execution with rich formatting and context
|
|
4
|
+
argument-hint: the parallel execution function and backend type
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Improve error handling for the specified parallel execution function to provide clean, user-focused tracebacks similar to direct function calls.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
1. **Filter Internal Frames**: Remove framework/library internal frames from tracebacks, showing only user code
|
|
12
|
+
2. **Add Context Lines**: Display 3 lines before and after each error location with line numbers
|
|
13
|
+
3. **Include Caller Frame**: Show where the parallel execution function was called, not just where the error occurred
|
|
14
|
+
4. **Rich Formatting**: Use rich library's Panel/formatting for clean, readable output
|
|
15
|
+
5. **Suppress Noise**: Set environment variables or flags to suppress verbose framework error logs
|
|
16
|
+
|
|
17
|
+
## Implementation Steps
|
|
18
|
+
|
|
19
|
+
1. **Capture Caller Context**: Use `inspect.currentframe().f_back` to capture where the parallel function was called (filename, line number, function name)
|
|
20
|
+
|
|
21
|
+
2. **Wrap Error Handling**: Catch framework-specific exceptions (e.g., `RayTaskError`, thread exceptions) in the execution loop
|
|
22
|
+
|
|
23
|
+
3. **Parse/Extract Original Exception**: Get the underlying user exception from the framework wrapper
|
|
24
|
+
- Extract exception type, message, and traceback information
|
|
25
|
+
- Parse from string representation if traceback objects aren't preserved
|
|
26
|
+
|
|
27
|
+
4. **Filter Frames**: Skip frames matching internal paths:
|
|
28
|
+
- Framework internals (e.g., `ray/_private`, `concurrent/futures`)
|
|
29
|
+
- Library worker implementations (e.g., `speedy_utils/multi_worker`)
|
|
30
|
+
- Site-packages for the framework
|
|
31
|
+
|
|
32
|
+
5. **Format with Context**:
|
|
33
|
+
- For each user frame, show: `filepath:lineno in function_name`
|
|
34
|
+
- Use `linecache.getline()` to retrieve surrounding lines
|
|
35
|
+
- Highlight the error line with `❱` marker
|
|
36
|
+
- Number all lines (e.g., ` 4 │ code here` or ` 5 ❱ error here`)
|
|
37
|
+
|
|
38
|
+
6. **Display Caller Frame First**: Show where the parallel function was invoked before showing the actual error location
|
|
39
|
+
|
|
40
|
+
7. **Clean Exit**: Flush output streams before exiting to ensure traceback displays
|
|
41
|
+
|
|
42
|
+
## Example Output Format
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
╭─────────────── Traceback (most recent call last) ───────────────╮
|
|
46
|
+
│ /path/to/user/script.py:42 in main │
|
|
47
|
+
│ │
|
|
48
|
+
│ 40 │ data = load_data() │
|
|
49
|
+
│ 41 │ # Process in parallel │
|
|
50
|
+
│ 42 ❱ results = multi_process(process_item, data, workers=8) │
|
|
51
|
+
│ 43 │ │
|
|
52
|
+
│ │
|
|
53
|
+
│ /path/to/user/module.py:15 in process_item │
|
|
54
|
+
│ │
|
|
55
|
+
│ 12 │ def process_item(item): │
|
|
56
|
+
│ 13 │ value = item['key'] │
|
|
57
|
+
│ 14 │ denominator = value - 100 │
|
|
58
|
+
│ 15 ❱ return 1 / denominator │
|
|
59
|
+
│ 16 │ │
|
|
60
|
+
╰──────────────────────────────────────────────────────────────────╯
|
|
61
|
+
ZeroDivisionError: division by zero
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Apply these improvements to the specified parallel execution function, ensuring error messages are as clear as direct function calls while maintaining all performance benefits of parallel execution.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: speedy-utils
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.44
|
|
4
4
|
Summary: Fast and easy-to-use package for data science
|
|
5
5
|
Project-URL: Homepage, https://github.com/anhvth/speedy
|
|
6
6
|
Project-URL: Repository, https://github.com/anhvth/speedy
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
21
|
Requires-Dist: aiohttp
|
|
22
22
|
Requires-Dist: bump2version
|
|
23
23
|
Requires-Dist: cachetools
|
|
@@ -39,6 +39,7 @@ Requires-Dist: pydantic
|
|
|
39
39
|
Requires-Dist: pytest
|
|
40
40
|
Requires-Dist: ray
|
|
41
41
|
Requires-Dist: requests
|
|
42
|
+
Requires-Dist: rich>=14.3.1
|
|
42
43
|
Requires-Dist: ruff
|
|
43
44
|
Requires-Dist: scikit-learn
|
|
44
45
|
Requires-Dist: tabulate
|
|
@@ -57,13 +58,48 @@ Description-Content-Type: text/markdown
|
|
|
57
58
|
|
|
58
59
|
**Speedy Utils** is a Python utility library designed to streamline common programming tasks such as caching, parallel processing, file I/O, and data manipulation. It provides a collection of decorators, functions, and classes to enhance productivity and performance in your Python projects.
|
|
59
60
|
|
|
61
|
+
## 🚀 Recent Updates (January 27, 2026)
|
|
62
|
+
|
|
63
|
+
**Enhanced Error Handling in Parallel Processing:**
|
|
64
|
+
- Rich-formatted error tracebacks with code context and syntax highlighting
|
|
65
|
+
- Three error handling modes: 'raise', 'ignore', and 'log'
|
|
66
|
+
- Filtered tracebacks focusing on user code (hiding infrastructure)
|
|
67
|
+
- Real-time progress reporting with error/success statistics
|
|
68
|
+
- Automatic error logging to timestamped files
|
|
69
|
+
- Caller frame information showing where parallel functions were invoked
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
### Parallel Processing with Error Handling
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from speedy_utils import multi_thread, multi_process
|
|
77
|
+
|
|
78
|
+
# Simple parallel processing
|
|
79
|
+
results = multi_thread(lambda x: x * 2, [1, 2, 3, 4, 5])
|
|
80
|
+
# Results: [2, 4, 6, 8, 10]
|
|
81
|
+
|
|
82
|
+
# Robust processing with error handling
|
|
83
|
+
def process_item(item):
|
|
84
|
+
if item == 3:
|
|
85
|
+
raise ValueError(f"Cannot process item {item}")
|
|
86
|
+
return item * 2
|
|
87
|
+
|
|
88
|
+
# Continue processing despite errors
|
|
89
|
+
results = multi_thread(process_item, [1, 2, 3, 4, 5], error_handler='log')
|
|
90
|
+
# Results: [2, 4, None, 8, 10] - errors logged automatically
|
|
91
|
+
```
|
|
92
|
+
|
|
60
93
|
## Table of Contents
|
|
61
94
|
|
|
95
|
+
- [🚀 Recent Updates](#-recent-updates-january-27-2026)
|
|
96
|
+
- [Quick Start](#quick-start)
|
|
62
97
|
- [Features](#features)
|
|
63
98
|
- [Installation](#installation)
|
|
64
99
|
- [Usage](#usage)
|
|
65
|
-
- [Caching](#caching)
|
|
66
100
|
- [Parallel Processing](#parallel-processing)
|
|
101
|
+
- [Enhanced Error Handling](#enhanced-error-handling)
|
|
102
|
+
- [Caching](#caching)
|
|
67
103
|
- [File I/O](#file-io)
|
|
68
104
|
- [Data Manipulation](#data-manipulation)
|
|
69
105
|
- [Utility Functions](#utility-functions)
|
|
@@ -72,11 +108,12 @@ Description-Content-Type: text/markdown
|
|
|
72
108
|
## Features
|
|
73
109
|
|
|
74
110
|
- **Caching Mechanisms**: Disk-based and in-memory caching to optimize function calls.
|
|
75
|
-
- **Parallel Processing**: Multi-threading, multi-processing, and asynchronous multi-threading utilities.
|
|
111
|
+
- **Parallel Processing**: Multi-threading, multi-processing, and asynchronous multi-threading utilities with enhanced error handling.
|
|
76
112
|
- **File I/O**: Simplified JSON, JSONL, and pickle file handling with support for various file extensions.
|
|
77
113
|
- **Data Manipulation**: Utilities for flattening lists and dictionaries, converting data types, and more.
|
|
78
114
|
- **Timing Utilities**: Tools to measure and log execution time of functions and processes.
|
|
79
115
|
- **Pretty Printing**: Enhanced printing functions for structured data, including HTML tables for Jupyter notebooks.
|
|
116
|
+
- **Enhanced Error Handling**: Rich error tracebacks with code context, configurable error handling modes ('raise', 'ignore', 'log'), and detailed progress reporting.
|
|
80
117
|
|
|
81
118
|
## Installation
|
|
82
119
|
|
|
@@ -161,20 +198,132 @@ result = compute_sum(5, 7) # Retrieved from in-memory cache
|
|
|
161
198
|
|
|
162
199
|
### Parallel Processing
|
|
163
200
|
|
|
164
|
-
#### Multi-threading
|
|
201
|
+
#### Multi-threading with Enhanced Error Handling
|
|
165
202
|
|
|
166
|
-
Execute functions concurrently using multiple threads
|
|
203
|
+
Execute functions concurrently using multiple threads with comprehensive error handling. The enhanced error handling provides three modes: 'raise' (default), 'ignore', and 'log'. When errors occur, you'll see rich-formatted tracebacks with code context and caller information.
|
|
167
204
|
|
|
168
205
|
```python
|
|
169
206
|
from speedy_utils import multi_thread
|
|
170
207
|
|
|
171
208
|
def process_item(item):
|
|
172
|
-
#
|
|
209
|
+
# Simulate processing that might fail
|
|
210
|
+
if item == 3:
|
|
211
|
+
raise ValueError(f"Invalid item: {item}")
|
|
173
212
|
return item * 2
|
|
174
213
|
|
|
175
214
|
items = [1, 2, 3, 4, 5]
|
|
176
|
-
|
|
177
|
-
|
|
215
|
+
|
|
216
|
+
# Default behavior: raise on first error with rich traceback
|
|
217
|
+
try:
|
|
218
|
+
results = multi_thread(process_item, items, workers=3)
|
|
219
|
+
except SystemExit:
|
|
220
|
+
print("Error occurred and was displayed with rich formatting")
|
|
221
|
+
|
|
222
|
+
# Continue processing on errors, return None for failed items
|
|
223
|
+
results = multi_thread(process_item, items, workers=3, error_handler='ignore')
|
|
224
|
+
print(results) # [2, 4, None, 8, 10]
|
|
225
|
+
|
|
226
|
+
# Log errors to files and continue processing
|
|
227
|
+
results = multi_thread(process_item, items, workers=3, error_handler='log', max_error_files=10)
|
|
228
|
+
print(results) # [2, 4, None, 8, 10] - errors logged to .cache/speedy_utils/error_logs/
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### Multi-processing with Error Handling
|
|
232
|
+
|
|
233
|
+
Process items across multiple processes with the same enhanced error handling capabilities.
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
from speedy_utils import multi_process
|
|
237
|
+
|
|
238
|
+
def risky_computation(x):
|
|
239
|
+
"""Computation that might fail for certain inputs."""
|
|
240
|
+
if x % 5 == 0:
|
|
241
|
+
raise RuntimeError(f"Cannot process multiples of 5: {x}")
|
|
242
|
+
return x ** 2
|
|
243
|
+
|
|
244
|
+
data = list(range(12))
|
|
245
|
+
|
|
246
|
+
# Process with error logging (continues on errors)
|
|
247
|
+
results = multi_process(
|
|
248
|
+
risky_computation,
|
|
249
|
+
data,
|
|
250
|
+
backend='mp',
|
|
251
|
+
error_handler='log',
|
|
252
|
+
max_error_files=5
|
|
253
|
+
)
|
|
254
|
+
print(results) # [0, 1, 4, 9, 16, None, 36, 49, 64, 81, None, 121]
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Enhanced Error Handling
|
|
258
|
+
|
|
259
|
+
**Speedy Utils** now provides comprehensive error handling for parallel processing with rich formatting and detailed diagnostics.
|
|
260
|
+
|
|
261
|
+
#### Rich Error Tracebacks
|
|
262
|
+
|
|
263
|
+
When errors occur, you'll see beautifully formatted tracebacks with:
|
|
264
|
+
- **Code context**: Lines of code around the error location
|
|
265
|
+
- **Caller information**: Shows where the parallel function was invoked
|
|
266
|
+
- **Filtered frames**: Focuses on user code, hiding infrastructure details
|
|
267
|
+
- **Color coding**: Easy-to-read formatting with syntax highlighting
|
|
268
|
+
|
|
269
|
+
#### Error Handling Modes
|
|
270
|
+
|
|
271
|
+
Choose how to handle errors in parallel processing:
|
|
272
|
+
|
|
273
|
+
- **`'raise'` (default)**: Stop on first error with detailed traceback
|
|
274
|
+
- **`'ignore'`**: Continue processing, return `None` for failed items
|
|
275
|
+
- **`'log'`**: Log errors to files and continue processing
|
|
276
|
+
|
|
277
|
+
#### Error Logging
|
|
278
|
+
|
|
279
|
+
When using `error_handler='log'`, errors are automatically saved to timestamped files in `.cache/speedy_utils/error_logs/` with full context and stack traces.
|
|
280
|
+
|
|
281
|
+
#### Progress Reporting with Error Statistics
|
|
282
|
+
|
|
283
|
+
Progress bars now show real-time error and success counts:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
Multi-thread [8/10] [00:02<00:00, 3.45it/s, success=8, errors=2, pending=0]
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
This makes it easy to monitor processing health at a glance.
|
|
290
|
+
|
|
291
|
+
#### Example: Robust Data Processing
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
from speedy_utils import multi_thread
|
|
295
|
+
|
|
296
|
+
def process_data_record(record):
|
|
297
|
+
"""Process a data record that might have issues."""
|
|
298
|
+
try:
|
|
299
|
+
# Your processing logic here
|
|
300
|
+
value = record['value'] / record['divisor']
|
|
301
|
+
return {'result': value, 'status': 'success'}
|
|
302
|
+
except KeyError as e:
|
|
303
|
+
raise ValueError(f"Missing required field in record: {e}")
|
|
304
|
+
except ZeroDivisionError:
|
|
305
|
+
raise ValueError("Division by zero in record")
|
|
306
|
+
|
|
307
|
+
# Sample data with some problematic records
|
|
308
|
+
data = [
|
|
309
|
+
{'value': 10, 'divisor': 2}, # OK
|
|
310
|
+
{'value': 15, 'divisor': 0}, # Will error
|
|
311
|
+
{'value': 20, 'divisor': 4}, # OK
|
|
312
|
+
{'value': 25}, # Missing divisor - will error
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
# Process with error logging - continues despite errors
|
|
316
|
+
results = multi_thread(
|
|
317
|
+
process_data_record,
|
|
318
|
+
data,
|
|
319
|
+
workers=4,
|
|
320
|
+
error_handler='log',
|
|
321
|
+
max_error_files=10
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
print("Results:", results)
|
|
325
|
+
# Output: Results: [{'result': 5.0, 'status': 'success'}, None, {'result': 5.0, 'status': 'success'}, None]
|
|
326
|
+
# Errors are logged to files for later analysis
|
|
178
327
|
```
|
|
179
328
|
|
|
180
329
|
### File I/O
|
|
@@ -6,13 +6,48 @@
|
|
|
6
6
|
|
|
7
7
|
**Speedy Utils** is a Python utility library designed to streamline common programming tasks such as caching, parallel processing, file I/O, and data manipulation. It provides a collection of decorators, functions, and classes to enhance productivity and performance in your Python projects.
|
|
8
8
|
|
|
9
|
+
## 🚀 Recent Updates (January 27, 2026)
|
|
10
|
+
|
|
11
|
+
**Enhanced Error Handling in Parallel Processing:**
|
|
12
|
+
- Rich-formatted error tracebacks with code context and syntax highlighting
|
|
13
|
+
- Three error handling modes: 'raise', 'ignore', and 'log'
|
|
14
|
+
- Filtered tracebacks focusing on user code (hiding infrastructure)
|
|
15
|
+
- Real-time progress reporting with error/success statistics
|
|
16
|
+
- Automatic error logging to timestamped files
|
|
17
|
+
- Caller frame information showing where parallel functions were invoked
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### Parallel Processing with Error Handling
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from speedy_utils import multi_thread, multi_process
|
|
25
|
+
|
|
26
|
+
# Simple parallel processing
|
|
27
|
+
results = multi_thread(lambda x: x * 2, [1, 2, 3, 4, 5])
|
|
28
|
+
# Results: [2, 4, 6, 8, 10]
|
|
29
|
+
|
|
30
|
+
# Robust processing with error handling
|
|
31
|
+
def process_item(item):
|
|
32
|
+
if item == 3:
|
|
33
|
+
raise ValueError(f"Cannot process item {item}")
|
|
34
|
+
return item * 2
|
|
35
|
+
|
|
36
|
+
# Continue processing despite errors
|
|
37
|
+
results = multi_thread(process_item, [1, 2, 3, 4, 5], error_handler='log')
|
|
38
|
+
# Results: [2, 4, None, 8, 10] - errors logged automatically
|
|
39
|
+
```
|
|
40
|
+
|
|
9
41
|
## Table of Contents
|
|
10
42
|
|
|
43
|
+
- [🚀 Recent Updates](#-recent-updates-january-27-2026)
|
|
44
|
+
- [Quick Start](#quick-start)
|
|
11
45
|
- [Features](#features)
|
|
12
46
|
- [Installation](#installation)
|
|
13
47
|
- [Usage](#usage)
|
|
14
|
-
- [Caching](#caching)
|
|
15
48
|
- [Parallel Processing](#parallel-processing)
|
|
49
|
+
- [Enhanced Error Handling](#enhanced-error-handling)
|
|
50
|
+
- [Caching](#caching)
|
|
16
51
|
- [File I/O](#file-io)
|
|
17
52
|
- [Data Manipulation](#data-manipulation)
|
|
18
53
|
- [Utility Functions](#utility-functions)
|
|
@@ -21,11 +56,12 @@
|
|
|
21
56
|
## Features
|
|
22
57
|
|
|
23
58
|
- **Caching Mechanisms**: Disk-based and in-memory caching to optimize function calls.
|
|
24
|
-
- **Parallel Processing**: Multi-threading, multi-processing, and asynchronous multi-threading utilities.
|
|
59
|
+
- **Parallel Processing**: Multi-threading, multi-processing, and asynchronous multi-threading utilities with enhanced error handling.
|
|
25
60
|
- **File I/O**: Simplified JSON, JSONL, and pickle file handling with support for various file extensions.
|
|
26
61
|
- **Data Manipulation**: Utilities for flattening lists and dictionaries, converting data types, and more.
|
|
27
62
|
- **Timing Utilities**: Tools to measure and log execution time of functions and processes.
|
|
28
63
|
- **Pretty Printing**: Enhanced printing functions for structured data, including HTML tables for Jupyter notebooks.
|
|
64
|
+
- **Enhanced Error Handling**: Rich error tracebacks with code context, configurable error handling modes ('raise', 'ignore', 'log'), and detailed progress reporting.
|
|
29
65
|
|
|
30
66
|
## Installation
|
|
31
67
|
|
|
@@ -110,20 +146,132 @@ result = compute_sum(5, 7) # Retrieved from in-memory cache
|
|
|
110
146
|
|
|
111
147
|
### Parallel Processing
|
|
112
148
|
|
|
113
|
-
#### Multi-threading
|
|
149
|
+
#### Multi-threading with Enhanced Error Handling
|
|
114
150
|
|
|
115
|
-
Execute functions concurrently using multiple threads
|
|
151
|
+
Execute functions concurrently using multiple threads with comprehensive error handling. The enhanced error handling provides three modes: 'raise' (default), 'ignore', and 'log'. When errors occur, you'll see rich-formatted tracebacks with code context and caller information.
|
|
116
152
|
|
|
117
153
|
```python
|
|
118
154
|
from speedy_utils import multi_thread
|
|
119
155
|
|
|
120
156
|
def process_item(item):
|
|
121
|
-
#
|
|
157
|
+
# Simulate processing that might fail
|
|
158
|
+
if item == 3:
|
|
159
|
+
raise ValueError(f"Invalid item: {item}")
|
|
122
160
|
return item * 2
|
|
123
161
|
|
|
124
162
|
items = [1, 2, 3, 4, 5]
|
|
125
|
-
|
|
126
|
-
|
|
163
|
+
|
|
164
|
+
# Default behavior: raise on first error with rich traceback
|
|
165
|
+
try:
|
|
166
|
+
results = multi_thread(process_item, items, workers=3)
|
|
167
|
+
except SystemExit:
|
|
168
|
+
print("Error occurred and was displayed with rich formatting")
|
|
169
|
+
|
|
170
|
+
# Continue processing on errors, return None for failed items
|
|
171
|
+
results = multi_thread(process_item, items, workers=3, error_handler='ignore')
|
|
172
|
+
print(results) # [2, 4, None, 8, 10]
|
|
173
|
+
|
|
174
|
+
# Log errors to files and continue processing
|
|
175
|
+
results = multi_thread(process_item, items, workers=3, error_handler='log', max_error_files=10)
|
|
176
|
+
print(results) # [2, 4, None, 8, 10] - errors logged to .cache/speedy_utils/error_logs/
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Multi-processing with Error Handling
|
|
180
|
+
|
|
181
|
+
Process items across multiple processes with the same enhanced error handling capabilities.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from speedy_utils import multi_process
|
|
185
|
+
|
|
186
|
+
def risky_computation(x):
|
|
187
|
+
"""Computation that might fail for certain inputs."""
|
|
188
|
+
if x % 5 == 0:
|
|
189
|
+
raise RuntimeError(f"Cannot process multiples of 5: {x}")
|
|
190
|
+
return x ** 2
|
|
191
|
+
|
|
192
|
+
data = list(range(12))
|
|
193
|
+
|
|
194
|
+
# Process with error logging (continues on errors)
|
|
195
|
+
results = multi_process(
|
|
196
|
+
risky_computation,
|
|
197
|
+
data,
|
|
198
|
+
backend='mp',
|
|
199
|
+
error_handler='log',
|
|
200
|
+
max_error_files=5
|
|
201
|
+
)
|
|
202
|
+
print(results) # [0, 1, 4, 9, 16, None, 36, 49, 64, 81, None, 121]
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Enhanced Error Handling
|
|
206
|
+
|
|
207
|
+
**Speedy Utils** now provides comprehensive error handling for parallel processing with rich formatting and detailed diagnostics.
|
|
208
|
+
|
|
209
|
+
#### Rich Error Tracebacks
|
|
210
|
+
|
|
211
|
+
When errors occur, you'll see beautifully formatted tracebacks with:
|
|
212
|
+
- **Code context**: Lines of code around the error location
|
|
213
|
+
- **Caller information**: Shows where the parallel function was invoked
|
|
214
|
+
- **Filtered frames**: Focuses on user code, hiding infrastructure details
|
|
215
|
+
- **Color coding**: Easy-to-read formatting with syntax highlighting
|
|
216
|
+
|
|
217
|
+
#### Error Handling Modes
|
|
218
|
+
|
|
219
|
+
Choose how to handle errors in parallel processing:
|
|
220
|
+
|
|
221
|
+
- **`'raise'` (default)**: Stop on first error with detailed traceback
|
|
222
|
+
- **`'ignore'`**: Continue processing, return `None` for failed items
|
|
223
|
+
- **`'log'`**: Log errors to files and continue processing
|
|
224
|
+
|
|
225
|
+
#### Error Logging
|
|
226
|
+
|
|
227
|
+
When using `error_handler='log'`, errors are automatically saved to timestamped files in `.cache/speedy_utils/error_logs/` with full context and stack traces.
|
|
228
|
+
|
|
229
|
+
#### Progress Reporting with Error Statistics
|
|
230
|
+
|
|
231
|
+
Progress bars now show real-time error and success counts:
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
Multi-thread [8/10] [00:02<00:00, 3.45it/s, success=8, errors=2, pending=0]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
This makes it easy to monitor processing health at a glance.
|
|
238
|
+
|
|
239
|
+
#### Example: Robust Data Processing
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
from speedy_utils import multi_thread
|
|
243
|
+
|
|
244
|
+
def process_data_record(record):
|
|
245
|
+
"""Process a data record that might have issues."""
|
|
246
|
+
try:
|
|
247
|
+
# Your processing logic here
|
|
248
|
+
value = record['value'] / record['divisor']
|
|
249
|
+
return {'result': value, 'status': 'success'}
|
|
250
|
+
except KeyError as e:
|
|
251
|
+
raise ValueError(f"Missing required field in record: {e}")
|
|
252
|
+
except ZeroDivisionError:
|
|
253
|
+
raise ValueError("Division by zero in record")
|
|
254
|
+
|
|
255
|
+
# Sample data with some problematic records
|
|
256
|
+
data = [
|
|
257
|
+
{'value': 10, 'divisor': 2}, # OK
|
|
258
|
+
{'value': 15, 'divisor': 0}, # Will error
|
|
259
|
+
{'value': 20, 'divisor': 4}, # OK
|
|
260
|
+
{'value': 25}, # Missing divisor - will error
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
# Process with error logging - continues despite errors
|
|
264
|
+
results = multi_thread(
|
|
265
|
+
process_data_record,
|
|
266
|
+
data,
|
|
267
|
+
workers=4,
|
|
268
|
+
error_handler='log',
|
|
269
|
+
max_error_files=10
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
print("Results:", results)
|
|
273
|
+
# Output: Results: [{'result': 5.0, 'status': 'success'}, None, {'result': 5.0, 'status': 'success'}, None]
|
|
274
|
+
# Errors are logged to files for later analysis
|
|
127
275
|
```
|
|
128
276
|
|
|
129
277
|
### File I/O
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "speedy-utils"
|
|
3
|
-
version = "1.1.
|
|
3
|
+
version = "1.1.44"
|
|
4
4
|
description = "Fast and easy-to-use package for data science"
|
|
5
5
|
authors = [{ name = "AnhVTH", email = "anhvth.226@gmail.com" }]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = { text = "MIT" }
|
|
8
|
-
requires-python = ">=3.
|
|
8
|
+
requires-python = ">=3.9"
|
|
9
9
|
dependencies = [
|
|
10
10
|
"numpy",
|
|
11
11
|
"requests",
|
|
@@ -33,6 +33,7 @@ dependencies = [
|
|
|
33
33
|
"ray",
|
|
34
34
|
"aiohttp",
|
|
35
35
|
"pytest",
|
|
36
|
+
"rich>=14.3.1",
|
|
36
37
|
]
|
|
37
38
|
classifiers = [
|
|
38
39
|
"Development Status :: 4 - Beta",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# type: ignore
|
|
2
|
+
from speedy_utils import multi_process, multi_thread
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def do_something(x):
|
|
6
|
+
if x % 3 == 0:
|
|
7
|
+
raise ValueError(f'Error at index {x}')
|
|
8
|
+
return x * 2
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
inputs = range(10)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == '__main__':
|
|
15
|
+
print('Testing error_handler="log" with mp backend:')
|
|
16
|
+
results = multi_process(
|
|
17
|
+
do_something,
|
|
18
|
+
inputs,
|
|
19
|
+
backend='mp',
|
|
20
|
+
error_handler='log',
|
|
21
|
+
max_error_files=5,
|
|
22
|
+
)
|
|
23
|
+
print(f'Results: {results}')
|
|
24
|
+
print()
|
|
25
|
+
|
|
26
|
+
# print('Testing error_handler="log" with multi_thread:')
|
|
27
|
+
# results = multi_thread(
|
|
28
|
+
# do_something,
|
|
29
|
+
# inputs,
|
|
30
|
+
# error_handler='log',
|
|
31
|
+
# max_error_files=5,
|
|
32
|
+
# )
|
|
33
|
+
# print(f'Results: {results}')
|
|
34
|
+
|