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).