You could define an error catching type
function. For example wrap int
as:
def trytype(astr, fn=int):
try:
ret = fn(astr)
except ValueError:
ret = ('error', astr)
return ret
In [51]: parser = argparse.ArgumentParser()
In [52]: parser.add_argument('-f', type=trytype);
In [53]: parser.parse_args('-f 123'.split())
Out[53]: Namespace(f=123)
In [54]: parser.parse_args('-f abc'.split())
Out[54]: Namespace(f=('error', 'abc'))
This could be generalized to handle other type functions (may be a trytype factory function). Also make it catch all the error types (ValueError, TypeError, ArgumentTypeError). And customize the return value. Here I just returned a tuple with an 'error' string and the original string.
In [55]: from functools import partial
In [56]: partial(trytype, fn=float)
Out[56]: functools.partial(<function trytype at 0xac13a8e4>, fn=<class 'float'>)
In [57]: partial(trytype, fn=float)('12.34')
Out[57]: 12.34
In [58]: partial(trytype, fn=int)('12.34')
Out[58]: ('error', '12.34')
In [59]: partial(trytype, fn=str)('abc')
Out[59]: 'abc'
accept int in one argument and float in another:
In [60]: parser = argparse.ArgumentParser()
In [61]: parser.add_argument('-i', type=partial(trytype, fn=int));
In [62]: parser.add_argument('-f', type=partial(trytype, fn=float));
In [63]: parser.parse_args('-f abc -i123'.split())
Out[63]: Namespace(f=('error', 'abc'), i=123)
In [64]: parser.parse_args('-f 12.32 -ia23'.split())
Out[64]: Namespace(f=12.32, i=('error', 'a23'))
In [65]: parser.parse_args('-f 12e32 -ia23'.split())
Out[65]: Namespace(f=1.2e+33, i=('error', 'a23'))
In [66]: parser.parse_args('-f x2e32 -ia23'.split())
Out[66]: Namespace(f=('error', 'x2e32'), i=('error', 'a23'))