Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
On Monday, July 30, 2018 at 3:55:25 PM UTC-4, Kyle Lahnakoski wrote: > > Rudy, > > I think your proposal may be very specific to iterable context managers; > I don't think his proposal is specific to iterable context managers. You can have a with clause that is used in a following for clause. in which case, make a method that makes that assumption: > > > def iter_with(obj): > > with obj as context: > > yield from context > > and use it > > > g = ( > > f.read() > > for fn in filenames > > for f in iter_with(open(fn)) > > ) > > On 2018-07-30 15:15, Rudy Matela wrote: > > Hello, > > > > Do you think it would be nice to allow with statements inside genexps or > > list comprehensions? The functions __enter__ and __exit__ would be > > automatically called as iterables are traversed. I am thinking of > > drafting a PEP about this. Examples: > > > > > > This > > > > g = (f.read() for fn in filenames with open(fn) as f) > > > > would be equivalent to the following use of a generator function: > > > > def __gen(): > > for fn in filenames: > > with open(fn) as f: > > yield f.read() > > g = __gen() > > > > > > This > > > > list = [f.read() for fn in filenames with open(fn) as f] > > > > would be equivalent to the following: > > > > list = [] > > for fn in filenames: > > with open(fn) as f: > > list.append(f.read()) > > > > -- > > Rudy > > ___ > > Python-ideas mailing list > > python...@python.org > > https://mail.python.org/mailman/listinfo/python-ideas > > Code of Conduct: http://python.org/psf/codeofconduct/ > > ___ > Python-ideas mailing list > python...@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ > >___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
On 30/07/18 21:15, Rudy Matela wrote: > Hello, > > Do you think it would be nice to allow with statements inside genexps or > list comprehensions? The functions __enter__ and __exit__ would be > automatically called as iterables are traversed. I am thinking of > drafting a PEP about this. Examples: > > > This > > g = (f.read() for fn in filenames with open(fn) as f) > > would be equivalent to the following use of a generator function: > > def __gen(): > for fn in filenames: > with open(fn) as f: > yield f.read() > g = __gen() To sail around Oscar's concern, this should rather be def __gen(): for fn in filenames: with open(fn) as f: _v = f.read() yield _v But in this case I think it'd be clearer to make it an expression rather than a generator expression term: g = (f.read() with open(fn) as f for fn in filenames) where _ = f.read() with open(fn) as f is equivalent to with open(fn) as f: _ = f.read() Currently possibly (if silly) alternative: from functools import wraps class with_one_use: def __init__(self, context): self.__context = context def __getattr__(self, name): exc1 = False obj = self.__context.__enter__() try: temp = getattr(obj, name) except: exc1 = True if not self.__context.__exit__(*sys.exc_info()): raise else: if callable(temp): @wraps(temp) def f(*args, **kwargs): exc2 = False try: return temp(*args, **kwargs) except: exc2 = True if not self.__context.__exit__(*sys.exc_info()): raise finally: if not exc2: self.__context.__exit__(None, None, None) exc1 = True return f else: return temp finally: if not exc1: self.__context.__exit__(None, None, None) g = (with_one_use(open(fn)).read() for fn in filenames) -- Thomas > > > This > > list = [f.read() for fn in filenames with open(fn) as f] > > would be equivalent to the following: > > list = [] > for fn in filenames: > with open(fn) as f: > list.append(f.read()) > > -- > Rudy > ___ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
31.07.18 00:26, Oscar Benjamin пише: On 30 July 2018 at 20:15, Rudy Matela wrote: Yielding from a with block should be discouraged rather than given special syntax. There is essentially a contradiction between the meaning/purpose of yield (suspend indefinitely) and with (definitely call __exit__). If I partially iterate over g as in for line in g: break then at this point g is suspended and f.__exit__ has not been called, so the file is not closed. I may choose to iterate over g later or not, so it has to remain in suspension just in case. In practice if you do this in CPython then f.__exit__ will *probably* be invoked indirectly by g.__del__ if/when the gc collects g. This defeats the main point of using with-open though which is to avoid depending on the gc for closing files. Concur with Oscar. ___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
On 30/07/18 20:15, Rudy Matela wrote: Hello, Do you think it would be nice to allow with statements inside genexps or list comprehensions? The functions __enter__ and __exit__ would be automatically called as iterables are traversed. I am thinking of drafting a PEP about this. Examples: I was worried until I twigged that you meant adding a clause rather than a statement per se. How does this interact with the other clauses in a comprehension? I'm thinking of monstrosities like: g = (f.read() for fn in filenames if fn.endswith(".txt") with open(fn) as f for filenames in get_directory_listing(dir) if .) -- Rhodri James *-* Kynesim Ltd ___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
On 30 July 2018 at 20:15, Rudy Matela wrote: > Hello, Hi Rudy, > Do you think it would be nice to allow with statements inside genexps or > list comprehensions? The functions __enter__ and __exit__ would be > automatically called as iterables are traversed. I am thinking of > drafting a PEP about this. Examples: > > > This > > g = (f.read() for fn in filenames with open(fn) as f) > > would be equivalent to the following use of a generator function: > > def __gen(): > for fn in filenames: > with open(fn) as f: > yield f.read() > g = __gen() Yielding from a with block should be discouraged rather than given special syntax. There is essentially a contradiction between the meaning/purpose of yield (suspend indefinitely) and with (definitely call __exit__). If I partially iterate over g as in for line in g: break then at this point g is suspended and f.__exit__ has not been called, so the file is not closed. I may choose to iterate over g later or not, so it has to remain in suspension just in case. In practice if you do this in CPython then f.__exit__ will *probably* be invoked indirectly by g.__del__ if/when the gc collects g. This defeats the main point of using with-open though which is to avoid depending on the gc for closing files. -- Oscar ___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
Rudy, I think your proposal may be very specific to iterable context managers; in which case, make a method that makes that assumption: > def iter_with(obj): > with obj as context: > yield from context and use it > g = ( > f.read() > for fn in filenames > for f in iter_with(open(fn)) > ) On 2018-07-30 15:15, Rudy Matela wrote: > Hello, > > Do you think it would be nice to allow with statements inside genexps or > list comprehensions? The functions __enter__ and __exit__ would be > automatically called as iterables are traversed. I am thinking of > drafting a PEP about this. Examples: > > > This > > g = (f.read() for fn in filenames with open(fn) as f) > > would be equivalent to the following use of a generator function: > > def __gen(): > for fn in filenames: > with open(fn) as f: > yield f.read() > g = __gen() > > > This > > list = [f.read() for fn in filenames with open(fn) as f] > > would be equivalent to the following: > > list = [] > for fn in filenames: > with open(fn) as f: > list.append(f.read()) > > -- > Rudy > ___ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/ ___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions
Hello, Do you think it would be nice to allow with statements inside genexps or list comprehensions? The functions __enter__ and __exit__ would be automatically called as iterables are traversed. I am thinking of drafting a PEP about this. Examples: This g = (f.read() for fn in filenames with open(fn) as f) would be equivalent to the following use of a generator function: def __gen(): for fn in filenames: with open(fn) as f: yield f.read() g = __gen() This list = [f.read() for fn in filenames with open(fn) as f] would be equivalent to the following: list = [] for fn in filenames: with open(fn) as f: list.append(f.read()) -- Rudy ___ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/