Skip to content
Advertisement

Python Argparse – Add multiple arguments to a subparser

I am trying to make a serial terminal app with two different functions. One function lists out available serial ports and the other function opens the specified serial port at the specified baud rate.

What I am trying to attempt is be able to select between either listing the ports or opening a port, if the user selects opening a port then argparse will accept two arguments; the port number and the baud rate.

Using the offical documentation I wrote this code:

# def listPorts():
# def openPort(port, baud):

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
subparsers = parser.add_subparsers(title="actions")

parser_list = subparsers.add_parser('list')
parser_list.set_defaults(func=listPorts)

parser_open = subparsers.add_parser('open')
parser_open.add_argument("COM Port", help="port to open serial terminal")
parser_open.add_argument("Baud Rate", help="frequency of serial communication")
parser_open.set_defaults(func=openPort)

config=parser.parse_args()
config.func(config)

I have managed to get it partially working – the first function, list ports, will work as expected as it has no parameters; but the second function, open port, won’t work as expected because it has two parameters and instead I get the error:

python main.py open 5 9600

config.func(config._get_args) TypeError: openPort() missing 1 required positional argument: 'baud'

The issue is that I don’t know how to get argparse to accept multiple arguments for it’s subparsers.

Any help would be greatly appreciated, thanks in advance!

Advertisement

Answer

After:

config=parser.parse_args()

add a print(config).

You’ll see it’s a namespace object with listed attributes. One is config.func, which is the func you call.

In:

config.func(config)

You call the func, but you pass it the whole config object.

Both functions should accept one argument, this config object.

One can ignore it, since it won’t have any attributes that it needs. The other can fetch the two attributes it needs.

Change these two lines so it is easier to fetch the attributes:

parser_open.add_argument("port", help="port to open serial terminal")
parser_open.add_argument("baud", help="frequency of serial communication")

in the function

def open(config):
    port = config.port
    baud = config.baud
    ....

In effect I am telling you same thing that the # sub-command functions example does in the argparse docs. (e.g. the foo and bar functions).

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement