accepting file path or file object?

Peter Otten __peter__ at
Mon Nov 5 12:49:01 CET 2012

andrea crotti wrote:

> Quite often I find convenient to get a filename or a file object as
> argument of a function, and do something as below:
> def grep_file(regexp, filepath_obj):
>     """Check if the given text is found in any of the file lines, take
>     a path to a file or an opened file object
>     """
>     if isinstance(filepath_obj, basestring):
>         fobj = open(filepath_obj)
>     else:
>         fobj = filepath_obj
>     for line in fobj:
>         if, line):
>             return True
>     return False
> This makes it also more convenient to unit-test, since I can just pass
> a StringIO.  But then there are other problems, for example if I pass
> a file object is the caller that has to make sure to close the file
> handle..
> So I'm thinking if it's not just worth to skip the support for file
> objects and only use the filenames, which seems a more robust and
> consistent choice..
> Any comment/suggestions about this?

I sometimes do something like this:

$ cat
import re
import sys
from contextlib import contextmanager

def xopen(file=None, mode="r"):
    if hasattr(file, "read"):
        yield file
    elif file == "-":
        if "w" in mode:
            yield sys.stdout
            yield sys.stdin
        with open(file, mode) as f:
            yield f

def grep(stream, regex):
    search = re.compile(regex).search
    return any(search(line) for line in stream)

if len(sys.argv) == 1:
    print grep(["alpha", "beta", "gamma"], "gamma")
    with xopen(sys.argv[1]) as f:
        print grep(f, sys.argv[2])
$ python 
$ echo 'alpha beta gamma' | python - gamma
$ echo 'alpha beta gamma' | python - delta
$ python context
$ python gamma
$ python delta

More information about the Python-list mailing list