基准执行

bench execute 命令让你可以从命令行运行 Python 函数。这对于执行一次性任务、调试或运行自定义脚本非常有用。

该命令会自动建立数据库连接并为站点初始化 Frappe 框架,因此你可以直接调用与数据库交互的函数,无需编写任何初始化代码。

基本用法

bench --site [site-name] execute [path.to.method]

简单示例

bench --site frappe.test execute frappe.clear_cache

这会在你的站点上运行 frappe.clear_cache() 函数。

bench --site frappe.test execute frappe.utils.get_site_info

这会在你的站点上运行 frappe.utils.get_site_info() 函数并打印输出结果。

传递参数

你可以直接在方法名后面传递参数:

bench --site frappe.test execute frappe.get_doc User Administrator

这会调用 frappe.get_doc("User", "Administrator")。

bench --site frappe.test execute frappe.db.get_value DocType User name

这会调用 frappe.db.get_value("DocType", "User", "name")。

JSON 参数

参数会尽可能自动解析为 JSON:

bench --site frappe.test execute frappe.db.exists User Administrator

字符串 “Administrator” 会保持为字符串,但数字和布尔值会被转换:

bench --site frappe.test execute some_function 123 true false

这会传入整数 123 以及布尔值 True 和 False。

命名参数(kwargs)

使用 -- 前缀来指定命名参数:

bench --site frappe.test execute frappe.db.get_value --doctype User --filters '{"name":"Administrator"}' --fieldname email

这会调用:

frappe.db.get_value(doctype="User", filters={"name": "Administrator"}, fieldname="email")

布尔标志

不带值的命名参数会变为 True:

bench --site frappe.test execute frappe.get_list User --ignore_permissions

这会调用 frappe.get_list("User", ignore_permissions=True)。

混合使用位置参数和命名参数

bench --site frappe.test execute frappe.get_list User --limit 5

这会调用 frappe.get_list("User", limit=5)。

运行 Python 表达式

你可以直接运行 Python 表达式:

bench --site frappe.test execute "frappe.db.count('User')"

你可以调用不同类型的 Python 可调用对象:

# Method on a returned object
bench --site frappe.test execute "frappe.get_doc('User', 'Administrator').reload()"

更多示例

# Clear cache for a specific DocType
bench --site frappe.test execute frappe.clear_cache --doctype "Sales Order"

# Get a document
bench --site frappe.test execute frappe.get_doc User Administrator

# Count records
bench --site frappe.test execute frappe.db.count User

# Run a whitelisted method
bench --site frappe.test execute myapp.api.my_function --param1 value1 --param2 value2

# Check if a record exists
bench --site frappe.test execute frappe.db.exists User guest

# Get configuration value
bench --site frappe.test execute frappe.conf.get developer_mode

# Execute a DocType method
bench --site frappe.test execute "frappe.get_doc('User', 'Administrator').get_fullname()"

# Chain operations with Python expressions
bench --site frappe.test execute "frappe.get_doc('User', 'Administrator').add_roles('System Manager')"

性能分析

使用 --profile 标志来查看性能统计信息:

bench --site frappe.test execute frappe.db.get_list --profile --doctype "Sales Order" --limit 1000

这会按累计时间排序列出前 50% 的函数调用。

        42084 function calls (41224 primitive calls) in 0.094 seconds

   Ordered by: cumulative time
   List reduced from 801 to 401 due to restriction <0.5>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      3/2    0.000    0.000    0.091    0.046 {built-in method builtins.eval}
        1    0.000    0.000    0.091    0.091 <bench execute>:1(<module>)
        1    0.000    0.000    0.091    0.091 ~/frappe-bench/apps/frappe/frappe/database/database.py:830(get_list)
     11/1    0.000    0.000    0.091    0.091 ~/frappe-bench/apps/frappe/frappe/__init__.py:1337(get_list)
       31    0.000    0.000    0.073    0.002 ~/frappe-bench/apps/frappe/frappe/database/database.py:183(sql)
       29    0.000    0.000    0.072    0.002 ~/frappe-bench/apps/frappe/frappe/query_builder/utils.py:126(execute_query)
     18/5    0.000    0.000    0.071    0.014 ~/frappe-bench/apps/frappe/frappe/utils/caching.py:125(site_cache_wrapper)
    20/12    0.000    0.000    0.070    0.006 ~/frappe-bench/apps/frappe/frappe/model/meta.py:72(get_meta)
      7/3    0.000    0.000    0.070    0.023 ~/frappe-bench/apps/frappe/frappe/model/utils/__init__.py:132(is_virtual_doctype)
        2    0.000    0.000    0.069    0.034 ~/frappe-bench/apps/frappe/frappe/model/meta.py:149(__init__)
       31    0.000    0.000    0.066    0.002 ~/frappe-bench/apps/frappe/frappe/database/database.py:371(execute_query)
       31    0.000    0.000    0.066    0.002 ~/frappe-bench/env/lib/python3.14/site-packages/MySQLdb/cursors.py:162(execute)
       31    0.000    0.000    0.066    0.002 ~/frappe-bench/env/lib/python3.14/site-packages/MySQLdb/cursors.py:325(_query)
       31    0.000    0.000    0.065    0.002 ~/frappe-bench/env/lib/python3.14/site-packages/MySQLdb/connections.py:276(query)
       31    0.065    0.002    0.065    0.002 {function Connection.query at 0x10be545c0}
       16    0.000    0.000    0.056    0.003 ~/frappe-bench/apps/frappe/frappe/database/database.py:592(get_values)
        2    0.000    0.000    0.034    0.017 ~/frappe-bench/apps/frappe/frappe/model/meta.py:166(process)
     31/2    0.000    0.000    0.034    0.017 ~/frappe-bench/apps/frappe/frappe/model/document.py:187(__init__)
        2    0.000    0.000    0.034    0.017 ~/frappe-bench/apps/frappe/frappe/model/meta.py:157(load_from_db)
        2    0.000    0.000    0.034    0.017 ~/frappe-bench/apps/frappe/frappe/model/document.py:233(load_from_db)
     11/1    0.000    0.000    0.025    0.025 ~/frappe-bench/apps/frappe/frappe/model/qb_query.py:26(execute)
    27/13    0.000    0.000    0.022    0.002 ~/frappe-bench/apps/frappe/frappe/query_builder/utils.py:62(get_query)
        2    0.000    0.000    0.021    0.011 ~/frappe-bench/apps/frappe/frappe/model/meta.py:422(apply_property_setters)
        2    0.000    0.000    0.018    0.009 ~/frappe-bench/apps/frappe/frappe/model/document.py:304(load_children_from_db)
    27/13    0.000    0.000    0.018    0.001 ~/frappe-bench/apps/frappe/frappe/database/query.py:215(get_query)
        2    0.000    0.000    0.016    0.008 ~/frappe-bench/apps/frappe/frappe/database/database.py:514(get_value)
    27/13    0.000    0.000    0.015    0.001 ~/frappe-bench/apps/frappe/frappe/database/query.py:344(apply_fields)
        1    0.000    0.000    0.014    0.014 ~/frappe-bench/apps/frappe/frappe/database/query.py:1280(apply_field_permissions)
        1    0.000    0.000    0.013    0.013 ~/frappe-bench/apps/frappe/frappe/database/query.py:928(_get_cached_permitted_fields)
        1    0.000    0.000    0.013    0.013 ~/frappe-bench/apps/frappe/frappe/model/__init__.py:216(get_permitted_fields)
        1    0.000    0.000    0.013    0.013 ~/frappe-bench/apps/frappe/frappe/model/meta.py:677(get_permitted_fieldnames)
        1    0.000    0.000    0.013    0.013 ~/frappe-bench/apps/frappe/frappe/model/meta.py:720(get_permlevel_access)
        2    0.000    0.000    0.013    0.007 ~/frappe-bench/apps/frappe/frappe/__init__.py:384(get_roles)
        2    0.000    0.000    0.013    0.007 ~/frappe-bench/apps/frappe/frappe/permissions.py:522(get_roles)
        2    0.000    0.000    0.013    0.007 ~/frappe-bench/apps/frappe/frappe/utils/redis_wrapper.py:230(hget)
        1    0.000    0.000    0.013    0.013 ~/frappe-bench/apps/frappe/frappe/permissions.py:530(get)
        1    0.000    0.000    0.012    0.012 ~/frappe-bench/env/lib/python3.14/site-packages/redis/client.py:1163(get_message)
        1    0.000    0.000    0.012    0.012 ~/frappe-bench/env/lib/python3.14/site-packages/redis/client.py:979(parse_response)
        1    0.000    0.000    0.012    0.012 ~/frappe-bench/env/lib/python3.14/site-packages/redis/client.py:960(_execute)
       13    0.000    0.000    0.009    0.001 ~/frappe-bench/apps/frappe/frappe/model/meta.py:108(get_table_columns)
       13    0.000    0.000    0.009    0.001 ~/frappe-bench/apps/frappe/frappe/database/database.py:1356(get_table_columns)
       13    0.000    0.000    0.009    0.001 ~/frappe-bench/apps/frappe/frappe/database/database.py:1337(get_db_table_columns)

在多个站点上运行

在所有站点上执行命令:

bench --site all execute frappe.clear_cache

或在指定站点上执行:

bench --site site1.local --site site2.local execute frappe.clear_cache

注意事项

  • 数据库:成功时更改会自动提交,出错时会回滚
  • 返回值:返回值会以 JSON 格式打印;None 不打印任何内容
  • 错误处理:出错时会以错误码退出并打印完整的堆栈跟踪
  • 安全性:任何 Python 函数都可以执行,不仅限于白名单中的函数——在生产环境中请谨慎使用

使用 –args 和 –kwargs 选项(旧版)

> 注意:--args 和 --kwargs 选项是旧格式,不推荐使用。请改用上面展示的直接传参方式。

你必须使用 Python 语法来配合 --args 和 --kwargs 选项。这些值必须用引号括起来,并且会作为 Python 代码进行求值(使用 eval()),而不是作为 JSON 解析。

传递参数列表

bench --site frappe.test execute frappe.db.get_value --args "['User', 'Administrator', 'email']"

传递关键字参数字典

bench --site frappe.test execute frappe.db.set_value --kwargs "{'doctype': 'User', 'name': 'Administrator', 'fieldname': 'enabled', 'value': 1}"

组合使用

bench --site frappe.test execute frappe.db.get_value --args "['User', 'Administrator']" --kwargs "{'fieldname': 'email'}"