3

What I would like to do is when I enter a specific argument it starts a function, is this possible through argparse. So if I hit the add argument in my application it triggers the "add" function.

parser = argparse.ArgumentParser(description='to do list')
parser.add_argument('-a', '--add', help='add an item to the todo list')
parser.add_argument('-r', '--remove',)
parser.add_argument('-l', '--list',)
args = parser.parse_args()

def add(args):
    conn = sqlite3.connect('todo.db')
    c = conn.cursor()
    c.execute("INSERT INTO todo VALUES (args.add, timestamp)")
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
LinuxBill
  • 415
  • 1
  • 8
  • 19
  • I'm not sure what you mean by "triggers the add function". Could you give an example of what the output code would look like when a specific item is added (say, `--add foo`)? – David Robinson Oct 08 '13 at 14:59
  • 2
    I would recommend not blurring the line between argument parsing and computation like this. Let `argparse` populate the `args` namespace, then examine the object and take the appropriate actions in your script. – chepner Oct 08 '13 at 15:12
  • I agree with @chepner here. – mgilson Oct 08 '13 at 15:19
  • Ok i may well look for another way to do it if its not best practise. – LinuxBill Oct 08 '13 at 15:39
  • possible duplicate of [Using the argparse output to call functions](http://stackoverflow.com/questions/3454934/using-the-argparse-output-to-call-functions) – Ryne Everett Mar 27 '14 at 20:30

2 Answers2

7

Sure, you can just use add as the type parameter:

def add(args):
    conn = sqlite3.connect('todo.db')
    c = conn.cursor()
    c.execute("INSERT INTO todo VALUES (args, timestamp)")

parser.add_argument('-a', '--add', type=add)

If that's not good enough, you can subclass argparse.Action and pretty much get argparse to do whatever you want whenever it encounters an argument.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 2
    Note that this will cause the action to take effect immediately, before the remaining options are parsed. That may or may not matter, but it's something to keep in mind. – chepner Oct 08 '13 at 15:15
  • 2
    For his use case, yes. I just wanted to address it for future visitors who may try to adapt this solution to a different use case where it may trip them up. – chepner Oct 08 '13 at 15:25
  • Thanks for the input @chepner , currently thats not a problem but it may be for somebody in the future. – LinuxBill Oct 08 '13 at 15:38
  • The `action` class would be more consistent with `argparse` design. `type` is meant to convert string values, and give errors if that can't be done. `actions`, normally store values in the `namespace`, but can also invoke subparsers or print help and exit. But separating parsing and acting is even better. – hpaulj Oct 08 '13 at 20:57
  • @hpaulj -- Agreed. Perhaps I should have gone more in that direction for my answer. Ultimately, `type` works here and is easier, but as you've correctly argued, it is more of a hack than using an action -- And both are more hacky than parsing first and asking questions later :) – mgilson Oct 08 '13 at 21:07
3

Here's a solution in spirit with my comment to your question:

parser = argparse.ArgumentParser(description='to do list')
parser.add_argument('-a', '--add', action='append', help='add an item to the todo list')
parser.add_argument('-r', '--remove',)
parser.add_argument('-l', '--list',)
args = parser.parse_args()

def add(args):
    conn = sqlite3.connect('todo.db')
    c = conn.cursor()
    c.execute("INSERT INTO todo VALUES (args.add, timestamp)")

for item in args.add:
    add(item)

This simply collects the items to add to the DB while parsing. Once parsing is complete, you can call add on each item in the accumulated list.


Another option for triggering an arbitrary piece of code, if your intended usage permits, is to use a subcommand, the use of which would look like

$ myscript add "Get milk on the way home"
$ myscript add "Set DVR to record game"
$ myscript list

The use of subcommands provides an indication that myscript should take a specific action, rather than set a configuration option. I'll leave the implementation as an exercise; see the docs for details.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thanks for this i actually have opted for the subcommand options looks nicer :) Thanks for the heads up about that. Need to sort my SQl stuff or just use a text file. – LinuxBill Oct 08 '13 at 21:08