summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2020-12-20 18:14:54 (GMT)
committerGitHub <noreply@github.com>2020-12-20 18:14:54 (GMT)
commitb0398a4b7fb5743f6dbb72ac6b2926e0a0c11498 (patch)
tree43b30130f59d375ba5a841131840f18b10a8839a
parenta44ce6c9f725d336aea51a946b42769f29fed613 (diff)
downloadcpython-b0398a4b7fb5743f6dbb72ac6b2926e0a0c11498.zip
cpython-b0398a4b7fb5743f6dbb72ac6b2926e0a0c11498.tar.gz
cpython-b0398a4b7fb5743f6dbb72ac6b2926e0a0c11498.tar.bz2
bpo-42572: Improve argparse docs for the type parameter. (GH-23849)
-rw-r--r--Doc/library/argparse.rst107
1 files changed, 57 insertions, 50 deletions
diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
index 02cd70f..1a298cd 100644
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -1050,63 +1050,70 @@ command-line argument was not present::
type
^^^^
-By default, :class:`ArgumentParser` objects read command-line arguments in as simple
+By default, the parser reads command-line arguments in as simple
strings. However, quite often the command-line string should instead be
-interpreted as another type, like a :class:`float` or :class:`int`. The
-``type`` keyword argument of :meth:`~ArgumentParser.add_argument` allows any
-necessary type-checking and type conversions to be performed. Common built-in
-types and functions can be used directly as the value of the ``type`` argument::
+interpreted as another type, such as a :class:`float` or :class:`int`. The
+``type`` keyword for :meth:`~ArgumentParser.add_argument` allows any
+necessary type-checking and type conversions to be performed.
- >>> parser = argparse.ArgumentParser()
- >>> parser.add_argument('foo', type=int)
- >>> parser.add_argument('bar', type=open)
- >>> parser.parse_args('2 temp.txt'.split())
- Namespace(bar=<_io.TextIOWrapper name='temp.txt' encoding='UTF-8'>, foo=2)
+If the type_ keyword is used with the default_ keyword, the type converter
+is only applied if the default is a string.
-See the section on the default_ keyword argument for information on when the
-``type`` argument is applied to default arguments.
+The argument to ``type`` can be any callable that accepts a single string.
+If the function raises :exc:`ArgumentTypeError`, :exc:`TypeError`, or
+:exc:`ValueError`, the exception is caught and a nicely formatted error
+message is displayed. No other exception types are handled.
-To ease the use of various types of files, the argparse module provides the
-factory FileType which takes the ``mode=``, ``bufsize=``, ``encoding=`` and
-``errors=`` arguments of the :func:`open` function. For example,
-``FileType('w')`` can be used to create a writable file::
+Common built-in types and functions can be used as type converters:
- >>> parser = argparse.ArgumentParser()
- >>> parser.add_argument('bar', type=argparse.FileType('w'))
- >>> parser.parse_args(['out.txt'])
- Namespace(bar=<_io.TextIOWrapper name='out.txt' encoding='UTF-8'>)
-
-``type=`` can take any callable that takes a single string argument and returns
-the converted value::
-
- >>> def perfect_square(string):
- ... value = int(string)
- ... sqrt = math.sqrt(value)
- ... if sqrt != int(sqrt):
- ... msg = "%r is not a perfect square" % string
- ... raise argparse.ArgumentTypeError(msg)
- ... return value
- ...
- >>> parser = argparse.ArgumentParser(prog='PROG')
- >>> parser.add_argument('foo', type=perfect_square)
- >>> parser.parse_args(['9'])
- Namespace(foo=9)
- >>> parser.parse_args(['7'])
- usage: PROG [-h] foo
- PROG: error: argument foo: '7' is not a perfect square
+.. testcode::
-The choices_ keyword argument may be more convenient for type checkers that
-simply check against a range of values::
+ import argparse
+ import pathlib
- >>> parser = argparse.ArgumentParser(prog='PROG')
- >>> parser.add_argument('foo', type=int, choices=range(5, 10))
- >>> parser.parse_args(['7'])
- Namespace(foo=7)
- >>> parser.parse_args(['11'])
- usage: PROG [-h] {5,6,7,8,9}
- PROG: error: argument foo: invalid choice: 11 (choose from 5, 6, 7, 8, 9)
-
-See the choices_ section for more details.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('count', type=int)
+ parser.add_argument('distance', type=float)
+ parser.add_argument('street', type=ascii)
+ parser.add_argument('code_point', type=ord)
+ parser.add_argument('source_file', type=open)
+ parser.add_argument('dest_file', type=argparse.FileType('w', encoding='latin-1'))
+ parser.add_argument('datapath', type=pathlib.Path)
+
+User defined functions can be used as well:
+
+.. doctest::
+
+ >>> def hyphenated(string):
+ ... return '-'.join([word[:4] for word in string.casefold().split()])
+ ...
+ >>> parser = argparse.ArgumentParser()
+ >>> _ = parser.add_argument('short_title', type=hyphenated)
+ >>> parser.parse_args(['"The Tale of Two Cities"'])
+ Namespace(short_title='"the-tale-of-two-citi')
+
+The :func:`bool` function is not recommended as a type converter. All it does
+is convert empty strings to ``False`` and non-empty strings to ``True``.
+This is usually not what is desired.
+
+In general, the ``type`` keyword is a convenience that should only be used for
+simple conversions that can only raise one of the three supported exceptions.
+Anything with more interesting error-handling or resource management should be
+done downstream after the arguments are parsed.
+
+For example, JSON or YAML conversions have complex error cases that require
+better reporting than can be given by the ``type`` keyword. An
+:exc:`~json.JSONDecodeError` would not be well formatted and a
+:exc:`FileNotFound` exception would not be handled at all.
+
+Even :class:`~argparse.FileType` has its limitations for use with the ``type``
+keyword. If one argument uses *FileType* and then a subsequent argument fails,
+an error is reported but the file is not automatically closed. In this case, it
+would be better to wait until after the parser has run and then use the
+:keyword:`with`-statement to manage the files.
+
+For type checkers that simply check against a fixed set of values, consider
+using the choices_ keyword instead.
choices