Using if-else in "with" statement in Python

Question:

I want to open a file that may be gzipped or not. To open the file, I use either

with open(myfile, 'r') as f:
    some_func(f) # arbitrary function

or

import gzip
with gzip.open(myfile, 'r') as f:
    some_func(f)

I want to check if myfile has a gz extension or not, and then from there decide which with statement to use. Here’s what I have:

# myfile_gzipped is a Boolean variable that tells me whether it's gzipped or not
if myfile_gzipped:
    with gzip.open(myfile, 'rb') as f:
       some_func(f)
else:
    with open(myfile, 'r') as f:
       some_func(f)

How should I go about it, without having to repeat some_func(f)?

Asked By: irene

||

Answers:

if myfile_gzipped:
    f = gzip.open(myfile, 'rb')
else:
    f = open(myfile, 'r')
with f:
    some_func(f)

The result of open and gzip.open is a context manager. with invokes the entry and exit methods on context managers. There is nothing special in calling those functions inside the with statement itself.

Answered By: Amadan

You don’t have to put open and with on the same line.

You can open the file as one step, and then do with f later.

if myfile_gzipped:
    f = gzip.open(myfile, 'rb')
else:
    f = open(myfile, 'r')

with f:
   some_func(f)
Answered By: John Gordon

I find that ExitStacks can be helpful in these cases:

from contextlib import ExitStack

with ExitStack() as stack:
    if myfile_gzipped:
        f = stack.enter_context(gzip.open(myfile, 'rb'))
    else:
        f = stack.enter_context(open(myfile, 'r'))
    some_func(f)
Answered By: flakes

You can use the ternary operator to evaluate two different expressions based on a condition:

with gzip.open(myfile, 'rb') if myfile_gzipped else open(myfile, 'r') as f:
    some_func(f)
Answered By: blhsing
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.