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'}"