I just read the Lib/argparse.py code (class FileType) on http://hg.python.org/cpython/file/default/Lib/argparse.py. File objects are opened without the with statement. For safe file opening/closing, should I instead encapsulate my argparse.ArgumentParser() in a contextlib stack like below? I feel very stupid for asking a question like this, but I am very much in doubt about the proper procedure.
import argparse
import contextlib
import gzip
import os
import fileinput
import sys
def main():
with contextlib.ExitStack() as stack:
input = argparse(stack)
process_arguments(input)
def argparse(stack):
parser = argparse.ArgumentParser()
parser.add_argument('--input', default=[sys.stdin], nargs='+')
d_args = vars(parser.parse_args())
if d_args['input'] != [sys.stdin]:
input = stack.enter_context(fileinput.FileInput(
files=d_args['input'], openhook=hook_compressed_text))
else:
input = stack.enter_context(sys.stdin)
return input
def hook_compressed_text(filename, mode):
ext = os.path.splitext(filename)[1]
if ext == '.gz':
f = gzip.open(filename, mode + 't')
else:
f = open(filename, mode)
return f
Here the class FileType from Lib/argparse.py:
class FileType(object):
"""Factory for creating file object types
Instances of FileType are typically passed as type= arguments to the
ArgumentParser add_argument() method.
Keyword Arguments:
- mode -- A string indicating how the file is to be opened. Accepts the
same values as the builtin open() function.
- bufsize -- The file's desired buffer size. Accepts the same values as
the builtin open() function.
- encoding -- The file's encoding. Accepts the same values as the
builtin open() function.
- errors -- A string indicating how encoding and decoding errors are to
be handled. Accepts the same value as the builtin open() function.
"""
def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None):
self._mode = mode
self._bufsize = bufsize
self._encoding = encoding
self._errors = errors
def __call__(self, string):
# the special argument "-" means sys.std{in,out}
if string == '-':
if 'r' in self._mode:
return _sys.stdin
elif 'w' in self._mode:
return _sys.stdout
else:
msg = _('argument "-" with mode %r') % self._mode
raise ValueError(msg)
# all other arguments are used as file names
try:
return open(string, self._mode, self._bufsize, self._encoding,
self._errors)
except OSError as e:
message = _("can't open '%s': %s")
raise ArgumentTypeError(message % (string, e))