Passing argument to bench execute

Hello, is it possible to call a function that expects arguments with bench execute?

@RWEMA_Aimable,

use, --args or --kargs options to pass the arguments

e.g. bench execute --args "arg1, arg2, .., argN" method_name

for more information please check, bench execute --help

Thanks, Makarand

6 Likes

OK thanks got it

In my case bench execute --args “arg1” was not working
instead I used bench execute --args “{‘arg1’}” this worked for me.

3 Likes

Thank you. We should mention it in the docs.

This worked for me:

bench --site dev.erpnext.host  execute  --args "{'My Company Name'}" myApp.myApp.doctype.myDocType.myPythonModule.myMethod
erpdev@djst:~/frappe-bench-DJST$ tree -L 1 apps
apps
├── erpnext
├── frappe
└── myApp
    └── myApp
        └── doctype
            └── myDocType
                └── myPythonModule

Where myPythonModule is a file containing a method:

@frappe.whitelist()
def myMethod(company):
  msg = "Result :: {}".format("Ok")
  myLogger(msg)
  return { "returned": msg }

Output is:

{"returned": "Result :: Ok"}

Fun fact: unlike many bench commands it is not necessary to run it from the bench root directory

3 Likes

:confounded:
Grrrrr

… and since even that isn’t sufficiently obvious:

bench --site dev.erpnext.host execute \
     --args "{\"company\": 'My Company Name', \"item\": 'My Item'}" \
     myApp.myApp.doctype.myDocType.myPythonModule.myMethod
@frappe.whitelist()
def myMethod(company, item):
  msg = f"Company :: '{company}', Item :: '{item}'"
  return { "returned": msg }

Output:

{"returned": "Company :: 'My Company Name', Item :: 'My Item'"}

WHY?

Parameter order is not guaranteed!

If you have numerous arguments, like:

"{ 'doctype', 'txt', 'searchfield', 'start', 'page_len', 'filters' }"

Passed to :

@frappe.whitelist()
def myMethod(doctype, txt, searchfield, start, page_len, filters):
    print(f"doctype: {doctype}")
    print(f"txt: {txt}")
    print(f"searchfield: {searchfield}")
    print(f"start: {start}")
    print(f"page_len: {page_len}")
    print(f"filters: {filters}")

You will end up with:

doctype: searchfield
txt: start
searchfield: txt
start: page_len
page_len: filters
filters: doctype
2 Likes

The Parameter order varies because your call passes a Set, which does not maintain the order of its items. Change your call like this using square brackets to create a List of parameters:

bench execute --args "[ 'doctype', 'txt', 'searchfield', 'start', 'page_len', 'filters' ]" myApp.myApp.doctype.myDocType.myPythonModule.myMethod

Just for other readers: methods you want to call don’t need the @frappe.whitelist()-annotation.

You can also use ‘kwargs’ if this fits your need better:

bench execute --kwargs "{'msg': 'Hallo Welt', 'value': 12}" erpituc.ituchelper.try_it.test_kwargs

def test_kwargs(**args):
    print(args)
    print(args.get("msg"))
    print(args.get("value"))

Output:
{‘msg’: ‘Hallo Welt’, ‘value’: 12}
Hallo Welt
12

1 Like

Finally: you may also like to use “bench console” instead of “bench execute”. This gives you a CLI like python, but with a preset environment for frappe.

bench console
Apps in this namespace:
frappe, erpnext, erpituc

In [1]: import erpituc.ituchelper.try_it as try_it

In [2]: try_it.test(1,2,3,4,5)
1
2
3
4
5
def test(arg1, arg2, arg3, arg4, arg5):
    print(arg1)
    print(arg2)
    print(arg3)
    print(arg4)
    print(arg5)
1 Like

as an alternative you can create custom bench commands as part of your app

custom bench commands can use the https://click.palletsprojects.com to build rich cli

2 Likes