funckeeper


Namefunckeeper JSON
Version 0.1.3 PyPI version JSON
download
home_pagehttps://github.com/xiwen-haochi/funckeeper
SummaryA Python function execution recorder and tracker
upload_time2024-12-02 02:47:37
maintainerNone
docs_urlNone
author'fkl'
requires_python>=3.6
licenseMIT
keywords python function tracker recorder debugging
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Funckeeper
- 🚧 警告:这是一个自用开源的项目!
- 📝 记录函数的执行过程和结果
- 🔍 追踪函数执行的详细信息(参数、返回值、执行时间等)
- 📊 统计分析函数的执行情况
- 🐛 捕获和分析函数执行中的错误
- 📤 支持导出分析报告(HTML格式)

## 目的

`funckeeper` 是一个专注于 Python 函数执行记录和追踪的工具,主要用于解决以下场景:

1. **源码追溯**:当脚本文件被删除或修改后,可以通过 funckeeper 查看历史执行记录中保存的源代码,帮助恢复或重建脚本。

2. **功能回溯**:通过记录的函数文档说明、执行参数和结果,帮助开发者快速回忆和理解之前编写的脚本功能。

3. **执行分析**:
   - 记录函数的执行时间、参数、返回值等详细信息
   - 统计函数的调用次数、成功率、平均执行时间等
   - 分析函数执行过程中的错误类型和频率

4. **报告生成**:支持将执行记录、统计信息导出为HTML格式的报告,便于分享和归档。

所有执行信息都会被存储在 SQLite 数据库中,方便后续查询和分析。通过这些数据,开发者可以:
- 追溯历史执行的脚本内容和功能
- 分析函数执行效率和稳定性
- 快速定位和解决常见错误
- 生成详细的执行报告
- 重现函数执行环境
- 追踪历史脚本的依赖需求
- 确保代码迁移时的依赖完整性

## 使用手册

### 安装

确保你已经安装了 Python 3.6 及以上版本。你可以通过以下命令安装 `funckeeper`:

```bash
pip install funckeeper
```

### 基本用法

1. **初始化 `FuncKeeper` 实例**

   ```python
   from funckeeper import FuncKeeper

   keeper = FuncKeeper()
   ```

2. **装饰函数**

   使用 `FuncKeeper` 实例作为装饰器来装饰你想要记录的函数:

   ```python
   @keeper(tags=["example", "demo"])
   def my_function(x, y):
       """这是一个简单的加法函数"""
       return x + y
   ```

3. **执行函数**

   调用被装饰的函数,`funckeeper` 会自动记录执行信息:

   ```python
   result = my_function(3, 4)
   ```

4. **导出数据**

   你可以导出函数的执行详情、统计信息或执行列表:

   ```python
   keeper.export_data(data, export_type='detail', output_dir='exports')
   ```

## 示例

### 示例 1: 记录函数执行

```python
@keeper(tags=["math", "addition"])
def add(a, b):
    """返回两个数的和"""
    return a + b

add(5, 7)
```

**执行结果:**

- 函数名: `add`
- 执行时间: `2024-11-27 18:13:47`
- 耗时: `0.0001s`
- 返回值: `12`
- 标签: `math, addition`

### 示例 2: 导出执行详情

```python
data = keeper.get_record_detail(1)
keeper.export_data(data, export_type='detail', output_dir='exports')
```

**生成的HTML文件:**

- 文件名: `funckeeper_detail_20241127_181347.html`
- 包含函数的执行详情,包括参数、返回值、执行时间等。

### 高级用法示例

### 示例 3: 获取函数统计信息

```python
from funckeeper import FuncKeeper
from datetime import datetime

keeper = FuncKeeper('test.db')

# 获取所有函数的统计信息
stats = keeper.get_statistics()

# 获取特定时间范围内的统计信息
start_date = datetime(2024, 1, 1)
end_date = datetime(2024, 12, 31)
stats = keeper.get_statistics(
    func_name="my_func",
    start_date=start_date,
    end_date=end_date,
    status="success"
)

# 打印统计信息
keeper.print_statistics(stats)
```

**执行结果:**
```
=== 函数统计: my_func ===
总调用次数: 9
成功次数: 9
失败次数: 0
成功率: 100.00%
平均执行时间: 0.0111s
最短执行时间: 0.0035s
最长执行时间: 0.0241s
首次调用: 2024-11-28 02:18:26
最后调用: 2024-11-28 02:28:40
```

### 示例 4: 搜索执行记录

```python
# 按关键字和标签搜索
results = keeper.search(
    keyword="calculate",
    tags=["math", "important"],
    status="error",
    start_date=datetime(2024, 1, 1),
    end_date=datetime(2024, 12, 31)
)
```

**执行结果:**
```
找到 1 条记录:

--- 记录 1 ---
记录ID: 11
函数名: divide
文档说明: 除法函数,计算 a 除以 b 的结果
执行时间: 2024-11-28 02:28:40
耗时: 0.0073s
调用参数: 1, 0
错误信息: division by zero
```

## 主要函数参数说明

### FuncKeeper 类

#### `get_statistics(func_name: str = None, start_date: datetime = None, end_date: datetime = None, status: str = None)`
- `func_name`: 要统计的函数名称(可选)
- `start_date`: 统计开始时间(可选)
- `end_date`: 统计结束时间(可选)
- `status`: 执行状态筛选,可选值:"success"或"error"

#### `search(keyword: str = None, tags: List[str] = None, status: str = None, start_date: datetime = None, end_date: datetime = None)`
- `keyword`: 搜索关键字,会匹配函数名、源代码、文档和错误信息
- `tags`: 标签列表,用于筛选特定标签的记录
- `status`: 执行状态筛选
- `start_date`: 搜索开始时间
- `end_date`: 搜索结束时间

#### `export_data(data: Any, export_type: str, output_dir: str = "exports")`
- `data`: 要导出的数据
- `export_type`: 导出类型,可选值:
  - "detail": 导出详细执行记录
  - "statistics": 导出统计信息
  - "list": 导出执行记录列表
- `output_dir`: 导出文件保存目录,默认为"exports"

### 示例 5: 完整的错误处理示例

```python
from funckeeper import FuncKeeper

keeper = FuncKeeper()

@keeper(tags=["math", "division"])
def divide(a, b):
    """安全除法函数"""
    try:
        return a / b
    except ZeroDivisionError as e:
        raise ValueError("除数不能为零") from e

# 测试正常情况
result = divide(10, 2)  # 返回 5.0

# 测试错误情况
try:
    result = divide(10, 0)
except ValueError as e:
    print(f"捕获到错误: {e}")

# 获取函数统计信息
stats = keeper.get_statistics(func_name="divide")
keeper.print_statistics(stats)
```

**执行结果:**
```
捕获到错误: 除数不能为零

=== 函数统计: divide ===
总调用次数: 12
成功次数: 10
失败次数: 2
成功率: 83.33%
平均执行时间: 0.0106s
最短执行时间: 0.0035s
最长执行时间: 0.0241s
首次调用: 2024-11-28 02:18:26
最后调用: 2024-11-28 03:27:28

错误类型分布:
- ValueError: 1次
- ZeroDivisionError: 1次
```
### 示例 6: 导出搜索结果

```python
    keeper = FuncKeeper(r"D:\1fkl\test.db")

    # 获取所有函数的统计信息
    @keeper(tags=["math", "division"])
    def divide(a, b):
        """安全除法函数"""
        try:
            return a / b
        except ZeroDivisionError as e:
            raise ValueError("除数不能为零") from e

    # 测试正常情况
    result = divide(10, 2)  # 返回 5.0

    # 测试错误情况
    try:
        result = divide(10, 0)
    except ValueError as e:
        print(f"捕获到错误: {e}")

    # 获取函数统计信息
    stats = keeper.get_statistics(func_name="divide")
    keeper.print_statistics(stats)
    # 导出搜索结果列表
    results = keeper.search(keyword="除法")
    if results:
        filepath = keeper.export_data(results, "list", r"D:\1fkl\exports")
        print(f"\n搜索结果已导出到: {filepath}")

    # # 导出详细信息
    if results:
        detail = keeper.get_record_detail(results[0]["id"])
        if detail:  # 确保有返回值
            filepath = keeper.export_data(detail, "detail", "exports")
            print(f"\n详细信息已导出到: {filepath}")

    # # 导出统计信息
    stats = keeper.get_statistics()
    filepath = keeper.export_data(stats, "statistics", "exports")
    print(f"\n统计信息已导出到: {filepath}")
```
```
--- 记录 1 ---
记录ID: 6
函数名: divide
文档说明: 安全除法函数
执行时间: 2024-11-28 06:03:24
耗时: 0.0084s
调用参数: 10, 0
错误信息: 除数不能为零

--- 记录 2 ---
记录ID: 5
函数名: divide
文档说明: 安全除法函数
执行时间: 2024-11-28 06:03:23
耗时: 0.0128s
调用参数: 10, 2
返回值: 5.0

--- 记录 3 ---
记录ID: 3
函数名: divide
文档说明: 安全除法函数
执行时间: 2024-11-28 06:03:04
耗时: 0.0000s
调用参数: 10, 2
返回值: 5.0

--- 记录 4 ---
记录ID: 4
函数名: divide
文档说明: 安全除法函数
执行时间: 2024-11-28 06:03:04
耗时: 0.0095s
调用参数: 10, 0
错误信息: 除数不能为零

--- 记录 5 ---
记录ID: 1
函数名: divide
文档说明: 安全除法函数
执行时间: 2024-11-28 06:02:16
耗时: 0.0114s
调用参数: 10, 2
返回值: 5.0

--- 记录 6 ---
记录ID: 2
函数名: divide
文档说明: 安全除法函数
执行时间: 2024-11-28 06:02:16
耗时: 0.0000s
调用参数: 10, 0
错误信息: 除数不能为零

搜索结果已导出到: D:\1fkl\exports\funckeeper_list_20241128_140324.html
```

### 导出html示例
![详情](docs/detail.png)
![列表](docs/list.png)
![统计](docs/tj.png)

这些示例展示了 `funckeeper` 的主要功能和使用场景,包括函数装饰、错误处理、统计分析和数据导出等特性。

## 许可证

`funckeeper` 遵循 MIT 许可证。详细信息请参阅 LICENSE 文件。
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/xiwen-haochi/funckeeper",
    "name": "funckeeper",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "python, function, tracker, recorder, debugging",
    "author": "'fkl'",
    "author_email": "18654198191@163.com",
    "download_url": "https://files.pythonhosted.org/packages/fd/04/be5a6642e377f6a37a8b2d2a571e56d10afdc249c16d5312f306aa302fa6/funckeeper-0.1.3.tar.gz",
    "platform": null,
    "description": "# Funckeeper\n- \ud83d\udea7 \u8b66\u544a\uff1a\u8fd9\u662f\u4e00\u4e2a\u81ea\u7528\u5f00\u6e90\u7684\u9879\u76ee\uff01\n- \ud83d\udcdd \u8bb0\u5f55\u51fd\u6570\u7684\u6267\u884c\u8fc7\u7a0b\u548c\u7ed3\u679c\n- \ud83d\udd0d \u8ffd\u8e2a\u51fd\u6570\u6267\u884c\u7684\u8be6\u7ec6\u4fe1\u606f\uff08\u53c2\u6570\u3001\u8fd4\u56de\u503c\u3001\u6267\u884c\u65f6\u95f4\u7b49\uff09\n- \ud83d\udcca \u7edf\u8ba1\u5206\u6790\u51fd\u6570\u7684\u6267\u884c\u60c5\u51b5\n- \ud83d\udc1b \u6355\u83b7\u548c\u5206\u6790\u51fd\u6570\u6267\u884c\u4e2d\u7684\u9519\u8bef\n- \ud83d\udce4 \u652f\u6301\u5bfc\u51fa\u5206\u6790\u62a5\u544a\uff08HTML\u683c\u5f0f\uff09\n\n## \u76ee\u7684\n\n`funckeeper` \u662f\u4e00\u4e2a\u4e13\u6ce8\u4e8e Python \u51fd\u6570\u6267\u884c\u8bb0\u5f55\u548c\u8ffd\u8e2a\u7684\u5de5\u5177\uff0c\u4e3b\u8981\u7528\u4e8e\u89e3\u51b3\u4ee5\u4e0b\u573a\u666f\uff1a\n\n1. **\u6e90\u7801\u8ffd\u6eaf**\uff1a\u5f53\u811a\u672c\u6587\u4ef6\u88ab\u5220\u9664\u6216\u4fee\u6539\u540e\uff0c\u53ef\u4ee5\u901a\u8fc7 funckeeper \u67e5\u770b\u5386\u53f2\u6267\u884c\u8bb0\u5f55\u4e2d\u4fdd\u5b58\u7684\u6e90\u4ee3\u7801\uff0c\u5e2e\u52a9\u6062\u590d\u6216\u91cd\u5efa\u811a\u672c\u3002\n\n2. **\u529f\u80fd\u56de\u6eaf**\uff1a\u901a\u8fc7\u8bb0\u5f55\u7684\u51fd\u6570\u6587\u6863\u8bf4\u660e\u3001\u6267\u884c\u53c2\u6570\u548c\u7ed3\u679c\uff0c\u5e2e\u52a9\u5f00\u53d1\u8005\u5feb\u901f\u56de\u5fc6\u548c\u7406\u89e3\u4e4b\u524d\u7f16\u5199\u7684\u811a\u672c\u529f\u80fd\u3002\n\n3. **\u6267\u884c\u5206\u6790**\uff1a\n   - \u8bb0\u5f55\u51fd\u6570\u7684\u6267\u884c\u65f6\u95f4\u3001\u53c2\u6570\u3001\u8fd4\u56de\u503c\u7b49\u8be6\u7ec6\u4fe1\u606f\n   - \u7edf\u8ba1\u51fd\u6570\u7684\u8c03\u7528\u6b21\u6570\u3001\u6210\u529f\u7387\u3001\u5e73\u5747\u6267\u884c\u65f6\u95f4\u7b49\n   - \u5206\u6790\u51fd\u6570\u6267\u884c\u8fc7\u7a0b\u4e2d\u7684\u9519\u8bef\u7c7b\u578b\u548c\u9891\u7387\n\n4. **\u62a5\u544a\u751f\u6210**\uff1a\u652f\u6301\u5c06\u6267\u884c\u8bb0\u5f55\u3001\u7edf\u8ba1\u4fe1\u606f\u5bfc\u51fa\u4e3aHTML\u683c\u5f0f\u7684\u62a5\u544a\uff0c\u4fbf\u4e8e\u5206\u4eab\u548c\u5f52\u6863\u3002\n\n\u6240\u6709\u6267\u884c\u4fe1\u606f\u90fd\u4f1a\u88ab\u5b58\u50a8\u5728 SQLite \u6570\u636e\u5e93\u4e2d\uff0c\u65b9\u4fbf\u540e\u7eed\u67e5\u8be2\u548c\u5206\u6790\u3002\u901a\u8fc7\u8fd9\u4e9b\u6570\u636e\uff0c\u5f00\u53d1\u8005\u53ef\u4ee5\uff1a\n- \u8ffd\u6eaf\u5386\u53f2\u6267\u884c\u7684\u811a\u672c\u5185\u5bb9\u548c\u529f\u80fd\n- \u5206\u6790\u51fd\u6570\u6267\u884c\u6548\u7387\u548c\u7a33\u5b9a\u6027\n- \u5feb\u901f\u5b9a\u4f4d\u548c\u89e3\u51b3\u5e38\u89c1\u9519\u8bef\n- \u751f\u6210\u8be6\u7ec6\u7684\u6267\u884c\u62a5\u544a\n- \u91cd\u73b0\u51fd\u6570\u6267\u884c\u73af\u5883\n- \u8ffd\u8e2a\u5386\u53f2\u811a\u672c\u7684\u4f9d\u8d56\u9700\u6c42\n- \u786e\u4fdd\u4ee3\u7801\u8fc1\u79fb\u65f6\u7684\u4f9d\u8d56\u5b8c\u6574\u6027\n\n## \u4f7f\u7528\u624b\u518c\n\n### \u5b89\u88c5\n\n\u786e\u4fdd\u4f60\u5df2\u7ecf\u5b89\u88c5\u4e86 Python 3.6 \u53ca\u4ee5\u4e0a\u7248\u672c\u3002\u4f60\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u547d\u4ee4\u5b89\u88c5 `funckeeper`\uff1a\n\n```bash\npip install funckeeper\n```\n\n### \u57fa\u672c\u7528\u6cd5\n\n1. **\u521d\u59cb\u5316 `FuncKeeper` \u5b9e\u4f8b**\n\n   ```python\n   from funckeeper import FuncKeeper\n\n   keeper = FuncKeeper()\n   ```\n\n2. **\u88c5\u9970\u51fd\u6570**\n\n   \u4f7f\u7528 `FuncKeeper` \u5b9e\u4f8b\u4f5c\u4e3a\u88c5\u9970\u5668\u6765\u88c5\u9970\u4f60\u60f3\u8981\u8bb0\u5f55\u7684\u51fd\u6570\uff1a\n\n   ```python\n   @keeper(tags=[\"example\", \"demo\"])\n   def my_function(x, y):\n       \"\"\"\u8fd9\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u52a0\u6cd5\u51fd\u6570\"\"\"\n       return x + y\n   ```\n\n3. **\u6267\u884c\u51fd\u6570**\n\n   \u8c03\u7528\u88ab\u88c5\u9970\u7684\u51fd\u6570\uff0c`funckeeper` \u4f1a\u81ea\u52a8\u8bb0\u5f55\u6267\u884c\u4fe1\u606f\uff1a\n\n   ```python\n   result = my_function(3, 4)\n   ```\n\n4. **\u5bfc\u51fa\u6570\u636e**\n\n   \u4f60\u53ef\u4ee5\u5bfc\u51fa\u51fd\u6570\u7684\u6267\u884c\u8be6\u60c5\u3001\u7edf\u8ba1\u4fe1\u606f\u6216\u6267\u884c\u5217\u8868\uff1a\n\n   ```python\n   keeper.export_data(data, export_type='detail', output_dir='exports')\n   ```\n\n## \u793a\u4f8b\n\n### \u793a\u4f8b 1: \u8bb0\u5f55\u51fd\u6570\u6267\u884c\n\n```python\n@keeper(tags=[\"math\", \"addition\"])\ndef add(a, b):\n    \"\"\"\u8fd4\u56de\u4e24\u4e2a\u6570\u7684\u548c\"\"\"\n    return a + b\n\nadd(5, 7)\n```\n\n**\u6267\u884c\u7ed3\u679c:**\n\n- \u51fd\u6570\u540d: `add`\n- \u6267\u884c\u65f6\u95f4: `2024-11-27 18:13:47`\n- \u8017\u65f6: `0.0001s`\n- \u8fd4\u56de\u503c: `12`\n- \u6807\u7b7e: `math, addition`\n\n### \u793a\u4f8b 2: \u5bfc\u51fa\u6267\u884c\u8be6\u60c5\n\n```python\ndata = keeper.get_record_detail(1)\nkeeper.export_data(data, export_type='detail', output_dir='exports')\n```\n\n**\u751f\u6210\u7684HTML\u6587\u4ef6:**\n\n- \u6587\u4ef6\u540d: `funckeeper_detail_20241127_181347.html`\n- \u5305\u542b\u51fd\u6570\u7684\u6267\u884c\u8be6\u60c5\uff0c\u5305\u62ec\u53c2\u6570\u3001\u8fd4\u56de\u503c\u3001\u6267\u884c\u65f6\u95f4\u7b49\u3002\n\n### \u9ad8\u7ea7\u7528\u6cd5\u793a\u4f8b\n\n### \u793a\u4f8b 3: \u83b7\u53d6\u51fd\u6570\u7edf\u8ba1\u4fe1\u606f\n\n```python\nfrom funckeeper import FuncKeeper\nfrom datetime import datetime\n\nkeeper = FuncKeeper('test.db')\n\n# \u83b7\u53d6\u6240\u6709\u51fd\u6570\u7684\u7edf\u8ba1\u4fe1\u606f\nstats = keeper.get_statistics()\n\n# \u83b7\u53d6\u7279\u5b9a\u65f6\u95f4\u8303\u56f4\u5185\u7684\u7edf\u8ba1\u4fe1\u606f\nstart_date = datetime(2024, 1, 1)\nend_date = datetime(2024, 12, 31)\nstats = keeper.get_statistics(\n    func_name=\"my_func\",\n    start_date=start_date,\n    end_date=end_date,\n    status=\"success\"\n)\n\n# \u6253\u5370\u7edf\u8ba1\u4fe1\u606f\nkeeper.print_statistics(stats)\n```\n\n**\u6267\u884c\u7ed3\u679c:**\n```\n=== \u51fd\u6570\u7edf\u8ba1: my_func ===\n\u603b\u8c03\u7528\u6b21\u6570: 9\n\u6210\u529f\u6b21\u6570: 9\n\u5931\u8d25\u6b21\u6570: 0\n\u6210\u529f\u7387: 100.00%\n\u5e73\u5747\u6267\u884c\u65f6\u95f4: 0.0111s\n\u6700\u77ed\u6267\u884c\u65f6\u95f4: 0.0035s\n\u6700\u957f\u6267\u884c\u65f6\u95f4: 0.0241s\n\u9996\u6b21\u8c03\u7528: 2024-11-28 02:18:26\n\u6700\u540e\u8c03\u7528: 2024-11-28 02:28:40\n```\n\n### \u793a\u4f8b 4: \u641c\u7d22\u6267\u884c\u8bb0\u5f55\n\n```python\n# \u6309\u5173\u952e\u5b57\u548c\u6807\u7b7e\u641c\u7d22\nresults = keeper.search(\n    keyword=\"calculate\",\n    tags=[\"math\", \"important\"],\n    status=\"error\",\n    start_date=datetime(2024, 1, 1),\n    end_date=datetime(2024, 12, 31)\n)\n```\n\n**\u6267\u884c\u7ed3\u679c:**\n```\n\u627e\u5230 1 \u6761\u8bb0\u5f55:\n\n--- \u8bb0\u5f55 1 ---\n\u8bb0\u5f55ID: 11\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u9664\u6cd5\u51fd\u6570\uff0c\u8ba1\u7b97 a \u9664\u4ee5 b \u7684\u7ed3\u679c\n\u6267\u884c\u65f6\u95f4: 2024-11-28 02:28:40\n\u8017\u65f6: 0.0073s\n\u8c03\u7528\u53c2\u6570: 1, 0\n\u9519\u8bef\u4fe1\u606f: division by zero\n```\n\n## \u4e3b\u8981\u51fd\u6570\u53c2\u6570\u8bf4\u660e\n\n### FuncKeeper \u7c7b\n\n#### `get_statistics(func_name: str = None, start_date: datetime = None, end_date: datetime = None, status: str = None)`\n- `func_name`: \u8981\u7edf\u8ba1\u7684\u51fd\u6570\u540d\u79f0\uff08\u53ef\u9009\uff09\n- `start_date`: \u7edf\u8ba1\u5f00\u59cb\u65f6\u95f4\uff08\u53ef\u9009\uff09\n- `end_date`: \u7edf\u8ba1\u7ed3\u675f\u65f6\u95f4\uff08\u53ef\u9009\uff09\n- `status`: \u6267\u884c\u72b6\u6001\u7b5b\u9009\uff0c\u53ef\u9009\u503c\uff1a\"success\"\u6216\"error\"\n\n#### `search(keyword: str = None, tags: List[str] = None, status: str = None, start_date: datetime = None, end_date: datetime = None)`\n- `keyword`: \u641c\u7d22\u5173\u952e\u5b57\uff0c\u4f1a\u5339\u914d\u51fd\u6570\u540d\u3001\u6e90\u4ee3\u7801\u3001\u6587\u6863\u548c\u9519\u8bef\u4fe1\u606f\n- `tags`: \u6807\u7b7e\u5217\u8868\uff0c\u7528\u4e8e\u7b5b\u9009\u7279\u5b9a\u6807\u7b7e\u7684\u8bb0\u5f55\n- `status`: \u6267\u884c\u72b6\u6001\u7b5b\u9009\n- `start_date`: \u641c\u7d22\u5f00\u59cb\u65f6\u95f4\n- `end_date`: \u641c\u7d22\u7ed3\u675f\u65f6\u95f4\n\n#### `export_data(data: Any, export_type: str, output_dir: str = \"exports\")`\n- `data`: \u8981\u5bfc\u51fa\u7684\u6570\u636e\n- `export_type`: \u5bfc\u51fa\u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1a\n  - \"detail\": \u5bfc\u51fa\u8be6\u7ec6\u6267\u884c\u8bb0\u5f55\n  - \"statistics\": \u5bfc\u51fa\u7edf\u8ba1\u4fe1\u606f\n  - \"list\": \u5bfc\u51fa\u6267\u884c\u8bb0\u5f55\u5217\u8868\n- `output_dir`: \u5bfc\u51fa\u6587\u4ef6\u4fdd\u5b58\u76ee\u5f55\uff0c\u9ed8\u8ba4\u4e3a\"exports\"\n\n### \u793a\u4f8b 5: \u5b8c\u6574\u7684\u9519\u8bef\u5904\u7406\u793a\u4f8b\n\n```python\nfrom funckeeper import FuncKeeper\n\nkeeper = FuncKeeper()\n\n@keeper(tags=[\"math\", \"division\"])\ndef divide(a, b):\n    \"\"\"\u5b89\u5168\u9664\u6cd5\u51fd\u6570\"\"\"\n    try:\n        return a / b\n    except ZeroDivisionError as e:\n        raise ValueError(\"\u9664\u6570\u4e0d\u80fd\u4e3a\u96f6\") from e\n\n# \u6d4b\u8bd5\u6b63\u5e38\u60c5\u51b5\nresult = divide(10, 2)  # \u8fd4\u56de 5.0\n\n# \u6d4b\u8bd5\u9519\u8bef\u60c5\u51b5\ntry:\n    result = divide(10, 0)\nexcept ValueError as e:\n    print(f\"\u6355\u83b7\u5230\u9519\u8bef: {e}\")\n\n# \u83b7\u53d6\u51fd\u6570\u7edf\u8ba1\u4fe1\u606f\nstats = keeper.get_statistics(func_name=\"divide\")\nkeeper.print_statistics(stats)\n```\n\n**\u6267\u884c\u7ed3\u679c:**\n```\n\u6355\u83b7\u5230\u9519\u8bef: \u9664\u6570\u4e0d\u80fd\u4e3a\u96f6\n\n=== \u51fd\u6570\u7edf\u8ba1: divide ===\n\u603b\u8c03\u7528\u6b21\u6570: 12\n\u6210\u529f\u6b21\u6570: 10\n\u5931\u8d25\u6b21\u6570: 2\n\u6210\u529f\u7387: 83.33%\n\u5e73\u5747\u6267\u884c\u65f6\u95f4: 0.0106s\n\u6700\u77ed\u6267\u884c\u65f6\u95f4: 0.0035s\n\u6700\u957f\u6267\u884c\u65f6\u95f4: 0.0241s\n\u9996\u6b21\u8c03\u7528: 2024-11-28 02:18:26\n\u6700\u540e\u8c03\u7528: 2024-11-28 03:27:28\n\n\u9519\u8bef\u7c7b\u578b\u5206\u5e03:\n- ValueError: 1\u6b21\n- ZeroDivisionError: 1\u6b21\n```\n### \u793a\u4f8b 6: \u5bfc\u51fa\u641c\u7d22\u7ed3\u679c\n\n```python\n    keeper = FuncKeeper(r\"D:\\1fkl\\test.db\")\n\n    # \u83b7\u53d6\u6240\u6709\u51fd\u6570\u7684\u7edf\u8ba1\u4fe1\u606f\n    @keeper(tags=[\"math\", \"division\"])\n    def divide(a, b):\n        \"\"\"\u5b89\u5168\u9664\u6cd5\u51fd\u6570\"\"\"\n        try:\n            return a / b\n        except ZeroDivisionError as e:\n            raise ValueError(\"\u9664\u6570\u4e0d\u80fd\u4e3a\u96f6\") from e\n\n    # \u6d4b\u8bd5\u6b63\u5e38\u60c5\u51b5\n    result = divide(10, 2)  # \u8fd4\u56de 5.0\n\n    # \u6d4b\u8bd5\u9519\u8bef\u60c5\u51b5\n    try:\n        result = divide(10, 0)\n    except ValueError as e:\n        print(f\"\u6355\u83b7\u5230\u9519\u8bef: {e}\")\n\n    # \u83b7\u53d6\u51fd\u6570\u7edf\u8ba1\u4fe1\u606f\n    stats = keeper.get_statistics(func_name=\"divide\")\n    keeper.print_statistics(stats)\n    # \u5bfc\u51fa\u641c\u7d22\u7ed3\u679c\u5217\u8868\n    results = keeper.search(keyword=\"\u9664\u6cd5\")\n    if results:\n        filepath = keeper.export_data(results, \"list\", r\"D:\\1fkl\\exports\")\n        print(f\"\\n\u641c\u7d22\u7ed3\u679c\u5df2\u5bfc\u51fa\u5230: {filepath}\")\n\n    # # \u5bfc\u51fa\u8be6\u7ec6\u4fe1\u606f\n    if results:\n        detail = keeper.get_record_detail(results[0][\"id\"])\n        if detail:  # \u786e\u4fdd\u6709\u8fd4\u56de\u503c\n            filepath = keeper.export_data(detail, \"detail\", \"exports\")\n            print(f\"\\n\u8be6\u7ec6\u4fe1\u606f\u5df2\u5bfc\u51fa\u5230: {filepath}\")\n\n    # # \u5bfc\u51fa\u7edf\u8ba1\u4fe1\u606f\n    stats = keeper.get_statistics()\n    filepath = keeper.export_data(stats, \"statistics\", \"exports\")\n    print(f\"\\n\u7edf\u8ba1\u4fe1\u606f\u5df2\u5bfc\u51fa\u5230: {filepath}\")\n```\n```\n--- \u8bb0\u5f55 1 ---\n\u8bb0\u5f55ID: 6\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u5b89\u5168\u9664\u6cd5\u51fd\u6570\n\u6267\u884c\u65f6\u95f4: 2024-11-28 06:03:24\n\u8017\u65f6: 0.0084s\n\u8c03\u7528\u53c2\u6570: 10, 0\n\u9519\u8bef\u4fe1\u606f: \u9664\u6570\u4e0d\u80fd\u4e3a\u96f6\n\n--- \u8bb0\u5f55 2 ---\n\u8bb0\u5f55ID: 5\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u5b89\u5168\u9664\u6cd5\u51fd\u6570\n\u6267\u884c\u65f6\u95f4: 2024-11-28 06:03:23\n\u8017\u65f6: 0.0128s\n\u8c03\u7528\u53c2\u6570: 10, 2\n\u8fd4\u56de\u503c: 5.0\n\n--- \u8bb0\u5f55 3 ---\n\u8bb0\u5f55ID: 3\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u5b89\u5168\u9664\u6cd5\u51fd\u6570\n\u6267\u884c\u65f6\u95f4: 2024-11-28 06:03:04\n\u8017\u65f6: 0.0000s\n\u8c03\u7528\u53c2\u6570: 10, 2\n\u8fd4\u56de\u503c: 5.0\n\n--- \u8bb0\u5f55 4 ---\n\u8bb0\u5f55ID: 4\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u5b89\u5168\u9664\u6cd5\u51fd\u6570\n\u6267\u884c\u65f6\u95f4: 2024-11-28 06:03:04\n\u8017\u65f6: 0.0095s\n\u8c03\u7528\u53c2\u6570: 10, 0\n\u9519\u8bef\u4fe1\u606f: \u9664\u6570\u4e0d\u80fd\u4e3a\u96f6\n\n--- \u8bb0\u5f55 5 ---\n\u8bb0\u5f55ID: 1\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u5b89\u5168\u9664\u6cd5\u51fd\u6570\n\u6267\u884c\u65f6\u95f4: 2024-11-28 06:02:16\n\u8017\u65f6: 0.0114s\n\u8c03\u7528\u53c2\u6570: 10, 2\n\u8fd4\u56de\u503c: 5.0\n\n--- \u8bb0\u5f55 6 ---\n\u8bb0\u5f55ID: 2\n\u51fd\u6570\u540d: divide\n\u6587\u6863\u8bf4\u660e: \u5b89\u5168\u9664\u6cd5\u51fd\u6570\n\u6267\u884c\u65f6\u95f4: 2024-11-28 06:02:16\n\u8017\u65f6: 0.0000s\n\u8c03\u7528\u53c2\u6570: 10, 0\n\u9519\u8bef\u4fe1\u606f: \u9664\u6570\u4e0d\u80fd\u4e3a\u96f6\n\n\u641c\u7d22\u7ed3\u679c\u5df2\u5bfc\u51fa\u5230: D:\\1fkl\\exports\\funckeeper_list_20241128_140324.html\n```\n\n### \u5bfc\u51fahtml\u793a\u4f8b\n![\u8be6\u60c5](docs/detail.png)\n![\u5217\u8868](docs/list.png)\n![\u7edf\u8ba1](docs/tj.png)\n\n\u8fd9\u4e9b\u793a\u4f8b\u5c55\u793a\u4e86 `funckeeper` \u7684\u4e3b\u8981\u529f\u80fd\u548c\u4f7f\u7528\u573a\u666f\uff0c\u5305\u62ec\u51fd\u6570\u88c5\u9970\u3001\u9519\u8bef\u5904\u7406\u3001\u7edf\u8ba1\u5206\u6790\u548c\u6570\u636e\u5bfc\u51fa\u7b49\u7279\u6027\u3002\n\n## \u8bb8\u53ef\u8bc1\n\n`funckeeper` \u9075\u5faa MIT \u8bb8\u53ef\u8bc1\u3002\u8be6\u7ec6\u4fe1\u606f\u8bf7\u53c2\u9605 LICENSE \u6587\u4ef6\u3002",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Python function execution recorder and tracker",
    "version": "0.1.3",
    "project_urls": {
        "Homepage": "https://github.com/xiwen-haochi/funckeeper",
        "Repository": "https://github.com/xiwen-haochi/funckeeper"
    },
    "split_keywords": [
        "python",
        " function",
        " tracker",
        " recorder",
        " debugging"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6a81181f35ac025651ed1a8c59369fcd990012d02f2991468d845ca5a4671672",
                "md5": "1a09ee52682e3de799ed43dd2fcfad99",
                "sha256": "32f8f576363a8f89853c6bffa89aebe2b596f0675c53ac22ce74190029ea2117"
            },
            "downloads": -1,
            "filename": "funckeeper-0.1.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1a09ee52682e3de799ed43dd2fcfad99",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 14922,
            "upload_time": "2024-12-02T02:47:35",
            "upload_time_iso_8601": "2024-12-02T02:47:35.700033Z",
            "url": "https://files.pythonhosted.org/packages/6a/81/181f35ac025651ed1a8c59369fcd990012d02f2991468d845ca5a4671672/funckeeper-0.1.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fd04be5a6642e377f6a37a8b2d2a571e56d10afdc249c16d5312f306aa302fa6",
                "md5": "decb1b53fe358ba107aaf7a440e8b85e",
                "sha256": "a25d6e7dafcd578d3ba1ace7f85654e1a7b4d9bebe800fcb54a02af2734526ce"
            },
            "downloads": -1,
            "filename": "funckeeper-0.1.3.tar.gz",
            "has_sig": false,
            "md5_digest": "decb1b53fe358ba107aaf7a440e8b85e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 14876,
            "upload_time": "2024-12-02T02:47:37",
            "upload_time_iso_8601": "2024-12-02T02:47:37.081948Z",
            "url": "https://files.pythonhosted.org/packages/fd/04/be5a6642e377f6a37a8b2d2a571e56d10afdc249c16d5312f306aa302fa6/funckeeper-0.1.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-02 02:47:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "xiwen-haochi",
    "github_project": "funckeeper",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "funckeeper"
}
        
Elapsed time: 0.61778s