Let's say I want to open a text file for reading using the following syntax:
with open(fname,'r') as f: # do something pass
But if I detect that it ends with .gz, I would call gzip.open().
if fname.endswith('.gz'): with gzip.open(fname,'rt') as f: # do something pass else: with open(fname,'r') as f: # do something pass
If "do something" part is long and not convenient to write in a function (e.g. it would create a nested function, which cannot be serialized), what is the shortest way to call with either gzip.open or open based on the return of fname.endswith('.gz')?
You can bind either context manager to the same name and choose early:
if fname.endswith('.gz'): context = gzip.open(fname,'rt') else: context = open(fname,'r') with context as f: # do the same thing in either case
This allows for some nice patterns, for instance if the input is possibly an opened file handle then you could use
contextlib.nullcontext to get a no-op in the
with block for the given case.