Re: [Python-Dev] PEP 343 - Abstract Block Redux
Robert Brewer wrote: There's a typo in the code snippets at the moment. The translation of the above statement is: abc = EXPR exc = () # Or (None, None, None) ? try: try: VAR = abc.__enter__() BLOCK except: exc = sys.exc_info() raise finally: abc.__exit__(exc) I think you meant abc.__exit__(*exc). Assuming that, then exc = (None, None, None) makes the most sense. If exc_info() is going to be passed as a single arg, then I'd rather have the default exc = (), so I can simply check if exc: in the __exit__ method. Also, the call to __enter__() needs to be before the try/finally block (as it is in PEP 310). Otherwise we get the releasing a lock you failed to acquire problem. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: I've written up the specs for my PEP 340 redux proposal as a separate PEP, PEP 343. http://python.org/peps/pep-0343.html Those who have been following the thread Merging PEP 310 and PEP 340-redux? will recognize my proposal in that thread, which received mostly positive responses there. Please review and ask for clarifications of anything that's unclear. On the keyword front, the two keyword choices affect the naming conventions of templates differently, and I think need to be considered in that light. The naming convention for 'do' is shown in the current PEP 343. The issue I've noticed with it is that *functions* read well, but methods don't because things get out of sequence. That is, do locking(the_lock) reads well, but do the_lock.locking() does not. Whereas, using 'with', it can be written either way, and still read reasonably well (with locked(the_lock), with the_lock.locked()). The 'with' keyword also reads better if objects natively support use in 'with' blocks (with the_lock, with the_file). Guido's concern regarding file objects being reused inappropriately can be dealt with in the file __enter__ method: def __enter__(self): if self.closed: raise RuntimeError, Cannot reopen closed file handle Template generators have the exact same problem with reusability - the solution used there is raising a RuntimeError when __enter__() is called inappropriately. This would make sense as a standard idiom - if a statement template can't be reused, attempting to do so should trigger a RuntimeError the second time __enter__() is invoked. For files, it may then become the common practice to keep pathnames around, rather than open file handles. When you actually needed access to the file, the existing open builtin would suffice: with open(filename, rb) as f: for line in f: print line I've written out the PEP 343 examples below, assuming types acquire native with statement support (including Decimal contexts - I also give PEP 343 style code for Decimal contexts). PEP343 examples: 'with' keyword, native support in objects 1. A template for ensuring that a lock, acquired at the start of a block, is released when the block is left: # New methods on lock objects def __enter__(self): self.acquire() def __exit__(self, *args): self.release() Used as follows: with myLock: # Code here executes with myLock held. The lock is # guaranteed to be released when the block is left (even # if via return or by an uncaught exception). 2. A template for opening a file that ensures the file is closed when the block is left: # New methods on file objects def __enter__(self): if self.closed: raise RuntimeError, Cannot reopen closed file handle def __exit__(self, *args): self.close() Used as follows: with open(/etc/passwd) as f: for line in f: print line.rstrip() 3. A template for committing or rolling back a database transaction; this is written as a class rather than as a decorator since it requires access to the exception information: class transaction: def __init__(self, db): self.db = db def __enter__(self): self.db.begin() def __exit__(self, *args): if args and args[0] is not None: self.db.rollback() else: self.db.commit() Used as follows: with transaction(db): # Exceptions in this code cause a rollback 5. Redirect stdout temporarily: @with_template def redirected_stdout(new_stdout): save_stdout = sys.stdout sys.stdout = new_stdout yield None sys.stdout = save_stdout Used as follows: with open(filename, w) as f: with redirected_stdout(f): print Hello world This isn't thread-safe, of course, but neither is doing this same dance manually. In a single-threaded program (e.g., a script) it is a totally fine way of doing things. 6. A variant on opening() that also returns an error condition: @with_template def open_w_error(filename, mode=r): try: f = open(filename, mode) except IOError, err: yield None, err else: yield f, None f.close() Used as follows: with open_w_error(/etc/passwd, a) as f, err: if err: print IOError:, err else: f.write(guido::0:0::/:/bin/sh\n) 7.
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: I've written up the specs for my PEP 340 redux proposal as a separate PEP, PEP 343. http://python.org/peps/pep-0343.html Those who have been following the thread Merging PEP 310 and PEP 340-redux? will recognize my proposal in that thread, which received mostly positive responses there. Please review and ask for clarifications of anything that's unclear. intuitively, I'm -1 on this proposal. unlike the original design, all you get from this is the ability to add try/finally blocks to your code without ever writing a try/finally-clause (neither in your code or in the block controller). that doesn't strike me as especially pythonic. (neither does the argument that just because you can use a mechanism to write inscrutable code, such a mechanism must not be made available feel right; Python's design has always been about careful tradeoffs between policy and mechanism, but this is too much policy for my taste. the original PEP 340 might have been too clever, but this reduced version feels pretty pointless). /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Fredrik Lundh wrote: unlike the original design, all you get from this is the ability to add try/finally blocks to your code without ever writing a try/finally-clause (neither in your code or in the block controller). that doesn't strike me as especially pythonic. I think the key benefit relates to the fact that correctly written resource management code currently has to be split it into two pieces - the first piece before the try block (e.g. 'lock.acquire()', 'f = open()'), and the latter in the finally clause (e.g. 'lock.release()', 'f.close()'). PEP 343 (like PEP 310 before it) makes it possible to define the correct resource management *once*, and then invoke it via a 'with' (or 'do') statement. Instead of having to check for is this file closed properly?, as soon as you write or see with open(filename) as f:, you *know* that that file is going to be closed correctly. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Guido van Rossum [EMAIL PROTECTED] writes: [Michael Hudson, after much thinking aloud] Yeah, sorry about that :) Oh, I guess the point is that with a decorated generator you can yield a value to be used as VAR, rather than just discarding the value as here. Hmm. Right. (I thought it was worth quoting this for the benefit of other who went down the same trail but didn't quite make it to this destination.) If things were fiddled such that sys.exc_info() return non-Nones when a finally clause is being executed because of an exception, we don't really need this wart, do we? The problem is that sys.exc_info() almost always returns *something* -- it's usually the last exception that was *ever* caught, except in certain circumstances. Yeah, OK. I'll stop claiming to understand sys.exc_info() apart from the simple cases. [Michael again] Compare and contrast: @template def redirected_stdout(out): save_stdout = sys.stdout sys.stdout = out yield None sys.stdout = save_stdout class redirected_stdout(object): def __init__(self, output): self.output = output def __enter__(self): self.save_stdout = sys.stdout sys.stdout = self.output def __exit__(self): sys.stdout = self.save_stdout The former is shorter and contains less (well, no) 'self.'s, but I think I find the latter somewhat clearer. Tastes differ. I think the generator wins; more so when there's more state to remember. Certainly when there's more state to manage, yes. But both will be possible, so, *shrug*. It's not a big deal. [Michael quoting Guido] The added complexity is caused by the need to separate VAR from EXPR so that a generator can be used. I personally like this separation; I actually like that the anonymous block controller is logically separate from the variable bound by the construct. Nevertheless, I think I actually like this argument! (Repeated for the benefit of others.) I guess this means PEP 310 can be retracted. Finally, from PEP 343 rev 1.7: exc = () # Or (None, None, None) ? The latter, please. Cheers, mwh -- . - the pointyour article - . |- a long way | -- Christophe Rhodes, ucam.chat ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
On 5/14/05, Fredrik Lundh [EMAIL PROTECTED] wrote: Nick Coghlan wrote: PEP 343 (like PEP 310 before it) makes it possible to define the correct resource management *once*, and then invoke it via a 'with' (or 'do') statement. This is probably the main point for me - encapsulate the try...finally dance in such a way that the two parts are not separated by an (arbitrarily long) chunk of code. I hated the equivalent dances in C (usually malloc/free stuff in that case) and it feels awkward that this is the one real ugliness of C that Python hasn't fixed for me :-) sure, but even if you look at both the application code *and* the resource management, there are no clues that the with statement is really just a masked try/finally statement. just look at the generator example: acquire yield release what in this snippet tells you that the release part will run even if the external block raises an exception? I agree with this point, though. What I liked about the original PEP 340 was the fact that the generator was a template, with yield acting as a put the block here placeholder. but I still think that something closer to the original PEP 340 is a lot more useful. Overall, I'd agree. I'm still fond of the original PEP 340 in all its glory - the looping issue was a wart, but PEP 343 seems so stripped down as to be something entirely different, not just a fix to the looping issue. My view - PEP 343 get a +1 in preference to PEP 310. I'd like to see PEP 342 - that gets a +1 from me. Covering both these areas at once, PEP 340 would still probably be my preference, though. (I'm not convinced there's much chance of resurrecting it, though). Even it its limited form, I prefer PEP 343 to the status quo, though. Oh, and I'm leaning towards with as a keyword again, as a result of the works better with member functions argument. Paul. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Paul Moore wrote: On 5/14/05, Fredrik Lundh [EMAIL PROTECTED] wrote: Nick Coghlan wrote: PEP 343 (like PEP 310 before it) makes it possible to define the correct resource management *once*, and then invoke it via a 'with' (or 'do') statement. This is probably the main point for me - encapsulate the try...finally dance in such a way that the two parts are not separated by an (arbitrarily long) chunk of code. I hated the equivalent dances in C (usually malloc/free stuff in that case) and it feels awkward that this is the one real ugliness of C that Python hasn't fixed for me :-) sure, but even if you look at both the application code *and* the resource management, there are no clues that the with statement is really just a masked try/finally statement. just look at the generator example: acquire yield release what in this snippet tells you that the release part will run even if the external block raises an exception? I agree with this point, though. What I liked about the original PEP 340 was the fact that the generator was a template, with yield acting as a put the block here placeholder. I also think the generator as statement template works much better if the __exit__ method is able to inject the exception into the generator frame, rather than always calling next(). Maybe PEP 343 should drop any suggestion of using generators to define these things, and focus on the PEP 310 style templates. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
At 01:55 PM 5/14/2005 +0200, Fredrik Lundh wrote: also, come to think of it, adding a new statement just to hide try/finally statements is a waste of statement space. why not just enhance the existing try statement? let try with opening(file) as f: body except IOError: deal with the error (you have to do this anyway) behave like try: f = opening(file) try: try: body except: exc = sys.exc_info() else: exc = None finally: f.__cleanup__(exc) except IOError: deal with the error and you're done. (or you could use __enter__ and __exit__ instead, which would give you a variation of PEP-343-as-I-understand-it) I like this, if you take out the with part, change the method names to __try__ and __finally__, and allow try to work as a block on its own if you've specified an expression. i.e.: try opening(filename) as f: # do stuff try locking(self.__lock): # do stuff try redirecting_stdout(f): # something try decimal.Context(precision=23): # okay, this one's a little weird try self.__lock: # and so's this; nouns read better with a gerund wrapper and I'd make the translation be: try: __exc = () VAR = EXPR.__try__() try: try: BODY except: __exc = sys.exc_info() raise finally: EXPR.__finally__() # except/else/finally clauses here, if there were any in the original try but I still think that something closer to the original PEP 340 is a lot more useful. I agree, but mainly because I'd like to be able to allow try/finally around yield in generators, be able to pass exceptions into generators, and tell generators to release their resources. :) I do think that the PEP 340 template concept is much more elegant than the various PEP 310-derived approaches, though. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
[Fredrik Lundh] intuitively, I'm -1 on this proposal. So we need to do better. Do you just prefer all of PEP 340? What about the objections against it? The mostly unnecessary loopiness in particular? unlike the original design, all you get from this is the ability to add try/finally blocks to your code without ever writing a try/finally-clause (neither in your code or in the block controller). that doesn't strike me as especially pythonic. Would it be better if we pulled back in the generator exit handling from PEP 340? That's a pretty self-contained thing, and would let you write try/finally around the yield. (neither does the argument that just because you can use a mechanism to write inscrutable code, such a mechanism must not be made available feel right; Python's design has always been about careful tradeoffs between policy and mechanism, but this is too much policy for my taste. the original PEP 340 might have been too clever, but this reduced version feels pretty pointless). Maybe. It still solves the majority of use cases for PEP 340, most of which are try/finally abstractions. Maybe I'm overreacting to Raymond Chen's rant about flow-control macros -- but having had to maintain code once that was riddled with these, it rang very true. PEP 340 is still my favorite, but it seems there's too much opposition to it, so I'm trying to explore alternatives; at the same time I *really* dislike the complexities of some of the non-looping counterproposals (e.g. Nick Coghlan's PEP 3XX or the proposals that make every keyword associated with 'try' a method). -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Tidier Exceptions
On Fri, May 13, 2005, Greg Ewing wrote: Brett C. wrote: Seems like, especially if we require inheritance from a base exception class in Python 3000, exceptions should have standard 'arg' and 'traceback' attributes with a possible 'context' attribute (or always a 'context' attribute set to None if not a chained exception). Instead of an 'args' attribute, I'd suggest that the constructor take keyword arguments and store them in corresponding attributes. Then interested parties could retrieve them by name instead of having to remember their positions in the args tuple of the exception class concerned. Sounds reasonable, but it should be equally easy to handle:: raise MyError, message -- Aahz ([EMAIL PROTECTED]) * http://www.pythoncraft.com/ And if that makes me an elitist...I couldn't be happier. --JMS ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Python's Unicode width default (New Py_UNICODE doc)
M.-A. Lemburg wrote: It is important to be able to rely on a default that is used when no special options are given. The decision to use UCS2 or UCS4 is much too important to be left to a configure script. Should the choice be a runtime decision? I think it should be. That could mean two unicode types, a call similar to sys.setdefaultencoding(), a new unicode extension module, or something else. BTW, thanks for discussing these issues. I tried to write a patch to the unicode API documentation, but it's hard to know just what to write. I think I can say this: sometimes your strings are UTF-16, so you're working with code units that are not necessarily complete code points; sometimes your strings are UCS4, so you're working with code units that are also complete code points. The choice between UTF-16 and UCS4 is made at the time the Python interpreter is compiled and the default choice varies by operating system and configuration. Shane ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Tidier Exceptions
On May 14, 2005, at 2:34 PM, Aahz wrote: On Fri, May 13, 2005, Greg Ewing wrote: Sounds reasonable, but it should be equally easy to handle:: raise MyError, message Make that: raise MyError(message) There's really no reason for a multi-argument raise when exceptions are objects anyhow. James ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: [Fredrik Lundh] intuitively, I'm -1 on this proposal. Just to toss in my opinion, I prefer PEP 340 over 343 as well, but not so much to give 343 a -1 from me. [SNIP - question of how to handle argument against 340 being a loop which I never totally got since you know it ahead of time so you just deal with it] [SNIP] Maybe I'm overreacting to Raymond Chen's rant about flow-control macros -- but having had to maintain code once that was riddled with these, it rang very true. You might be overreacting. I read the essay and I understand his arguments having been taught how to program in Scheme. But I don't think this is as serious. People will have the semantics of the block statement explained to them so how that works will be clear. And at that point they just have to track down the generator or iterator that the block statement is using. If you think about it, how is it different than the implicit iter() call on a 'for' loop along with the implicit next() call each time through the loop? Just because there is an implicit closing call back into the block generator at the end of a block statement? Doesn't seem so bad to me or that much of a stretch from the magic of a 'for' loop to be that huge of a thing. I think Raymond was reeling against arbitrary macro creation that hides flow control. We don't have that here. What we have is a clearly defined statement that does some very handy syntactic sugar for us. It doesn't feel as arbitrary as what Lisp and Scheme allow you to do. PEP 340 is still my favorite, but it seems there's too much opposition to it, so I'm trying to explore alternatives; at the same time I *really* dislike the complexities of some of the non-looping counterproposals (e.g. Nick Coghlan's PEP 3XX or the proposals that make every keyword associated with 'try' a method). Nick's was obviously directly against looping, but, with no offense to Nick, how many other people were against it looping? It never felt like it was a screaming mass with pitchforks but more of a I don't love it, but I can deal crowd. And as for the overly complex examples, that I believed stemmed from people realizing what might be possible if the statement was extended and tweaked this way or that so as to be able to do just one more thing. But that happens with every proposal; seemed like standard feature creep. The reason we have a BDFL is to tell us that yes, we could get the jumbo sized candy bar for $2 more but there is no way you will be able to finish that much chocolate before it melts all over your hands and get it all over your nice PyCon t-shirt. But then again I don't know if you got private emails asking to see if PEP 340 weighed as much as wood so it could be burned at the stake for being a witch. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Python's Unicode width default (New Py_UNICODE doc)
On May 14, 2005, at 3:05 PM, Shane Hathaway wrote: M.-A. Lemburg wrote: It is important to be able to rely on a default that is used when no special options are given. The decision to use UCS2 or UCS4 is much too important to be left to a configure script. Should the choice be a runtime decision? I think it should be. That could mean two unicode types, a call similar to sys.setdefaultencoding(), a new unicode extension module, or something else. BTW, thanks for discussing these issues. I tried to write a patch to the unicode API documentation, but it's hard to know just what to write. I think I can say this: sometimes your strings are UTF-16, so you're working with code units that are not necessarily complete code points; sometimes your strings are UCS4, so you're working with code units that are also complete code points. The choice between UTF-16 and UCS4 is made at the time the Python interpreter is compiled and the default choice varies by operating system and configuration. Well, if you're going to make it runtime, you might as well do it right. Take away the restriction that the unicode type backing store is forced to be a particular encoding (i.e. get rid of PyUnicode_AS_UNICODE) and give it more flexibility. The implementation of NSString in OpenDarwin's libFoundation http:// libfoundation.opendarwin.org/ (BSD license), or the CFString implementation in Apple's CoreFoundation http://developer.apple.com/ darwin/cflite.html (APSL) would be an excellent place to look for how this can be done. Of course, for backwards compatibility reasons, this would have to be a new type that descends from basestring. text would probably be a good name for it. This would be an abstract implementation, where you can make concrete subclasses that actually implement the various operations as necessary. For example, you could have text_ucs2, text_ucs4, text_ascii, text_codec, etc. The bonus here is you can get people to shut up about space efficient representations, because you can use whatever makes sense. -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: [Nick Coghlan] Also, the call to __enter__() needs to be before the try/finally block (as it is in PEP 310). Otherwise we get the releasing a lock you failed to acquire problem. I did that on purpose. There's a separate object ('abc' in the pseudo-code of the translation) whose __enter__ and __exit__ methods are called, and in __enter__ it can keep track of the reversible actions it has taken. Consider an application where you have to acquire *two* locks regularly: def lockBoth(): got1 = got2 = False lock1.acquire(); got1 = True lock2.acquire(); got2 = True yield None if got2: lock2.release() if got1: lock1.release() If this gets interrupted after locking lock1 but before locking lock2, it still has some cleanup to do. That code is incorrect, though. Say lockBoth() acquires lock1 but then lock2.acquire() throws an exception. (Maybe the lock requires some I/O operation, and the operation fails.) The interpreter will never reach the yield statement and lock1 will never be released. You really have to write it like this: def lockBoth(): lock1.acquire() try: lock2.acquire() except: lock1.release() raise yield None try: lock2.release() finally: lock1.release() I know that this complicates simpler use cases, and I'm not 100% sure this is the right solution; but I don't know how else to handle this use case. If __enter__ raises an exception, it has to clean up after itself before propagating the exception. __exit__ shouldn't be called if __enter__ fails. Shane ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Brett C. wrote: Guido van Rossum wrote: PEP 340 is still my favorite, but it seems there's too much opposition to it, so I'm trying to explore alternatives; at the same time I *really* dislike the complexities of some of the non-looping counterproposals (e.g. Nick Coghlan's PEP 3XX or the proposals that make every keyword associated with 'try' a method). Nick's was obviously directly against looping, but, with no offense to Nick, how many other people were against it looping? It never felt like it was a screaming mass with pitchforks but more of a I don't love it, but I can deal crowd. PEP 340 is very nice, but it became less appealing to me when I saw what it would do to break and continue statements. text = 'diamond' for fn in filenames: opening(fn) as f: if text in f.read(): print 'I found the text in %s' % fn break I think it would be pretty surprising if the break didn't stop the loop. Here's a new suggestion for PEP 340: use one keyword to start a block you don't want to loop, and a different keyword to start a block that can loop. If you specify the non-looping keyword but the block template produces more than one result, a RuntimeError results. Here is example A, a non-looping block statement using try: text = 'diamond' for fn in filenames: try opening(fn) as f: if text in f.read(): print 'I found the text in %s' % fn break In example A, the break statement breaks the for loop. If the opening() iterator returns more than one result, a RuntimeError will be generated by the Python interpreter. Here is example B, a looping block statement using in, adapted from PEP 340: in auto_retry(3, IOError) as attempt: f = urllib.urlopen(http://python.org/peps/pep-0340.html;) print f.read() Note that I introduced no new keywords except as, and the syntax in both cases is currently illegal. Shane ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: [Nick Coghlan] Also, the call to __enter__() needs to be before the try/finally block (as it is in PEP 310). Otherwise we get the releasing a lock you failed to acquire problem. I did that on purpose. There's a separate object ('abc' in the pseudo-code of the translation) whose __enter__ and __exit__ methods are called, and in __enter__ it can keep track of the reversible actions it has taken. Consider an application where you have to acquire *two* locks regularly: def lockBoth(): got1 = got2 = False lock1.acquire(); got1 = True lock2.acquire(); got2 = True yield None if got2: lock2.release() if got1: lock1.release() If this gets interrupted after locking lock1 but before locking lock2, it still has some cleanup to do. I know that this complicates simpler use cases, and I'm not 100% sure this is the right solution; but I don't know how else to handle this use case. If we retained the ability to inject exceptions into generators, this would be written with the extremely natural: @with template: def lockboth(): lock1.acquire() try: lock2.acquire() try: yield finally: lock2.release() finally: lock1.release() Or, even more simply: @with_template: def lockboth(): with lock1: with lock2: yield I think Fredrik's intuition is on to something - PEP 343 has scaled the idea back *too* far by throwing away the injection of exceptions into generator templates, when the only major objection was to the looping nature of the proposal. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] [Python-checkins] python/nondist/peps pep-0343.txt, 1.8, 1.9
-was, under the covers, a (optential) looping construct. This +was, under the covers, a (potential) looping construct. This I'm glad I didn't fix this one. I thought he meant to use optional. Raymond Hettinger ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com