This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ncoghlan
Recipients barry, ezio.melotti, martin.panter, ncoghlan, pitrou, rhettinger, serhiy.storchaka, yselivanov
Date 2015-09-08.02:44:29
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1441680271.44.0.306464566247.issue25014@psf.upfronthosting.co.za>
In-reply-to
Content
Having spent a few days pondering this after Ezio first mentioned the concept to me on IRC, I'm rejecting this on the basis of "not every 3 line function needs to be in the standard library".

The vast majority of iterable CM use cases are going to fall into one of the following two categories:

* deterministic cleanup is needed regardless of success or failure
* non-deterministic cleanup is acceptable regardless of success or failure

In the former case, you don't continue iteration after the with statement ends, in the latter, you don't need to use the context manager aspects at all.

Those cases which don't fall into that category would generally be better served by an appropriately named helper function that conveys the author's intent, rather than describing what the function does internally:

    def chain_files(names):
        for name in names:
            with open(name) as f:
                yield from f

    def cat(fnames):
        for line in chain_files(fnames):
            print(line, end='')


The implementation of the helper function can then optionally be switched to a compositional approach without affecting the usage:

    def itercm(cm):
        with cm:
            yield from cm

    def iterfile(name):
        return itercm(open(name))

    def chain_files(names):
        return chain.from_iterable(iterfile(name) for name in names)

For the more concrete use case of "iterate over several files in sequence", we have the fileinput module: https://docs.python.org/3/library/fileinput.html

That already opens and closes files as it goes, so chain_files() can actually be implemented as:

    def chain_files(names):
        with fileinput.input(names) as files:
            return chain.from_iterable(files)
History
Date User Action Args
2015-09-08 02:44:31ncoghlansetrecipients: + ncoghlan, barry, rhettinger, pitrou, ezio.melotti, martin.panter, serhiy.storchaka, yselivanov
2015-09-08 02:44:31ncoghlansetmessageid: <1441680271.44.0.306464566247.issue25014@psf.upfronthosting.co.za>
2015-09-08 02:44:31ncoghlanlinkissue25014 messages
2015-09-08 02:44:29ncoghlancreate