I am using argument parser to allow passing port number to my program. I then try to validate the value, and one of the first tests is the is int test:
parser = argparse.ArgumentParser(description='Provides XML-RPC API.')
parser.add_argument('--port', dest='port', default=9666, type=int,
help='port to listen on, 9666 by default.');
args = parser.parse_args()
if args.port is not int:
raise TypeError("Port must be integer (%s given), use -h argument to get help."%(type(args.port).__name__))
if args.port>=65536 or args.port<=0:
raise IndexError("Port must be lower than 65536, 65535 is the maximum port number. Also, port can only be positive, non-zero number. Use -h argument to get help.")
if args.port<=1204:
print("Notice: ports up to 1024 are reserved to well known services, using this port numbers often leads to conflicts. Use -h argument to get help.")
Now whatever I do, I get the error:
Port must be integer (int given), use -h argument to get help.
I mean, what the hell? Even the error says it was int, so what's going on?
args.port is not int will return False if args.port was ever set to the int type:
args.port = int
args.port is int # True
or you re-bound int to the same object args.port already is bound to:
int = args.port
args.port is int # True
That is because is tests if two references are pointing to the exact same object.
Perhaps you were confused on how to test for the type of an object, for that you use the isinstance() function, or test the output of type():
type(args.port) is not int # False if args.port is a different type
not isinstance(args.port, int) # False if args.port is a different type and not a subclass either
This will never be the case either, because you configured your ArgumentParser option to only accept integers:
parser.add_argument('--port', dest='port', default=9666, type=int,
help='port to listen on, 9666 by default.')
The type=int argument is important, because that means that anything that cannot be interpreted as an integer will be rejected by the parser. You will never get past parser.parse_args() here:
>>> import argparse
>>> parser = argparse.ArgumentParser(description='Provides XML-RPC API.')
>>> parser.add_argument('--port', dest='port', default=9666, type=int,
... help='port to listen on, 9666 by default.')
_StoreAction(option_strings=['--port'], dest='port', nargs=None, const=None, default=9666, type=<type 'int'>, choices=None, help='port to listen on, 9666 by default.', metavar=None)
>>> parser.parse_args(['--port', 'not an integer'])
usage: [-h] [--port PORT]
: error: argument --port: invalid int value: 'not an integer'
That's because 'not an integer' cannot be converted by the int() function; a ValueError is raised and argparse translates that to an error message for you:
>>> int('not an integer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'not an integer'
You could supply your own conversation function that limits the range:
def portnumber(value):
port = int(value) # may raise ValueError
if not 0 <= port <= 65536:
raise ValueError('Not a valid port number')
return port
Then use that as the type:
parser.add_argument('--port', dest='port', default=9666, type=portnumber,
help='port to listen on, 9666 by default.')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With