Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make conditional "with" pretier

Tags:

python

Any advice on what is the proper 'pythonic' way for the following function. Do I have to split it into two functions?

def readSomething(fp=None):
    if fp:
        return fp.read(100)
    else:
        with open('default.txt', 'r') as fp:
            return fp.read(100)

I need something like this because the readSomething function may be called from another function that may or may not have the same file open.

For example, it may be called like this at some places:

def doSomethingWithSameFile():
    with open('default.txt') as fp:
         preample = fp.read(10)
         more_data = readSomething(fb)
         ...

or like that at other places:

def init():
    data = readSomething()
    ...
like image 945
599644 Avatar asked Jan 31 '26 09:01

599644


1 Answers

I don't think this is the right solution, but I think it's what you want.

import contextlib

def readSomething(fp=None):
    with contextlib.ExitStack() as stack:
        if not fp:
            fp = stack.enter_context(open('default.txt'))
        return fp.read(100)

I get the impression that you're going to duplicate this logic many functions like readSomething() so I'd recommend putting the ExitStack code into a decorator and wrapping the functions where you need this behavior.

You could also use a decorator. I don't use this kind of code, so the syntax below is almost certainly incomplete, but the general idea stands:

import functools

def fallback_to_default(fn):
    @functools.wraps(fn)
    def new_fn(fp=None, *args, **kwargs):
        with contextlib.ExitStack() as stack:
            if not fp:
                fp = stack.enter_context(open('default.txt'))
            return fn(fp, *args, **kwargs)
    return new_fn

@fallback_to_default
def readSomething(fp=None):
    return fp.read(100)
like image 137
Harvey Avatar answered Feb 03 '26 00:02

Harvey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!