Re: [Python-Dev] anonymous blocks
Shane Hathaway wrote: There's a lot of boilerplate code there. Using your suggestion, I could write that something like this: def transaction(): begin_transaction() try: continue except: abort_transaction() raise else: commit_transaction() with transaction(): changestuff() changemorestuff() For that to work, the behaviour would need to differ slightly from what I envisioned (which was that the 'continue' would be behaviourally equivalent to a 'yield None'). Alternatively, something equivalent to the above could be written as: def transaction(): begin_transaction() continue ex = sys.exc_info() if ex[0] is not None: abort_transaction(): else: commit_transaction(): Note that you could do this with a normal resource, too: class transaction(object): def __enter__(): begin_transaction() def __exit__(): ex = sys.exc_info() if ex[0] is not None: abort_transaction(): else: commit_transaction(): Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ 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
[Python-Dev] Re: anonymous blocks
Nick Coghlan wrote: > Interestingly, with this approach, "for dummy in my_resource()" would still > wrap > the block of code in the entrance/exit code (because my_resource *is* a > generator), but it wouldn't get the try/finally semantics. > > An alternative would be to replace the 'yield None' with a 'break' or > 'continue', and create an object which supports the resource protocol and NOT > the iterator protocol. Something like: > > def my_resource(): >print "Hi!" # Do entrance code >continue # Go on with the contents of the 'with' block >print "Bye!" # Do exit code > > (This is currently a SyntaxError, so it isn't ambiguous in any way) Oh, it is ambiguous, as soon as you insert a for/while statement in your resource function and want to call continue in there. Other than that, it's very neat. Maybe "yield" alone (which is always a SyntaxError) could be used. Reinhold -- Mail address is perfectly valid! ___ 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] anonymous blocks
Nick Coghlan wrote: > An alternative would be to replace the 'yield None' with a 'break' or > 'continue', and create an object which supports the resource protocol > and NOT the iterator protocol. Something like: > > def my_resource(): > print "Hi!" # Do entrance code > continue # Go on with the contents of the 'with' block > print "Bye!" # Do exit code > > (This is currently a SyntaxError, so it isn't ambiguous in any way) That's a very interesting suggestion. I've been lurking, thinking about a way to use something like PEP 310 to help manage database transactions. Here is some typical code that changes something under transaction control: begin_transaction() try: changestuff() changemorestuff() except: abort_transaction() raise else: commit_transaction() There's a lot of boilerplate code there. Using your suggestion, I could write that something like this: def transaction(): begin_transaction() try: continue except: abort_transaction() raise else: commit_transaction() with transaction(): changestuff() changemorestuff() 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
[Python-Dev] Error checking in init functions
I always wondered why there usually is very sloppy error checking in init functions. Usually it goes like this (I removed declarations and some other lines for clarity): PyMODINIT_FUNC PyInit_zlib(void) { m = Py_InitModule4("zlib", zlib_methods, zlib_module_documentation, (PyObject*)NULL,PYTHON_API_VERSION); ZlibError = PyErr_NewException("zlib.error", NULL, NULL); if (ZlibError != NULL) { Py_INCREF(ZlibError); PyModule_AddObject(m, "error", ZlibError); } PyModule_AddIntConstant(m, "MAX_WBITS", MAX_WBITS); PyModule_AddIntConstant(m, "DEFLATED", DEFLATED); ver = PyString_FromString(ZLIB_VERSION); if (ver != NULL) PyModule_AddObject(m, "ZLIB_VERSION", ver); PyModule_AddStringConstant(m, "__version__", "1.0"); } Why isn't the result checked in the PyModule_... functions? Why is the failure of PyErr_NewException silently ignored? The problem is that when one of these things fail (although they are probably supposed to NOT fail) you end up with a module missing something, without any error message. What would be the correct thing to do - I assume something like if (PyModule_AddIntConstant(m, "MAX_WBITS", MAX_WBITS)) { PyErr_Print(); return; } Thomas ___ 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] anonymous blocks
On 4/21/05, Guido van Rossum <[EMAIL PROTECTED]> wrote: >for dummy in synchronized(the_lock): >BODY > > or perhaps even (making "for VAR" optional in the for-loop syntax) > with > >in synchronized(the_lock): >BODY > > Then synchronized() could be written cleanly as follows: > >def synchronized(lock): >lock.acquire() >try: >yield None >finally: >lock.release() How is this different from: def synchronized(lock): def synch_fn(block): lock.acquire() try: block() finally: lock.release() return synch_fn @synchronized def foo(): BLOCK True, it's non-obvious that foo is being immediately executed, but regardless I like the way synchronized is defined, and doesn't use yield (which in my opinion is a non-obvious solution) ___ 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] Caching objects in memory
[Facundo Batista] > Is there a document that details which objects are cached in memory > (to not create the same object multiple times, for performance)? The caches get cleaned-up before Python exit's, so you can find them all listed together in the code in Python/pythonrun.c: /* Sundry finalizers */ PyMethod_Fini(); PyFrame_Fini(); PyCFunction_Fini(); PyTuple_Fini(); PyList_Fini(); PyString_Fini(); PyInt_Fini(); PyFloat_Fini(); #ifdef Py_USING_UNICODE /* Cleanup Unicode implementation */ _PyUnicode_Fini(); #endif 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
Re: [Python-Dev] Proper place to put extra args for building
Brett C. wrote: >>You means sysconfig.py, right? Right. > No, I mean Python's setup.py; line 174. Ah, ok. > You mean Distutils' sysconfig, right? I can change that as well if you want. Please do; otherwise, people might see strange effects. Regards, Martin ___ 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] Error checking in init functions
Thomas Heller <[EMAIL PROTECTED]> writes: > I always wondered why there usually is very sloppy error checking in > init functions. Laziness, I presume... > The problem is that when one of these things fail (although they are > probably supposed to NOT fail) you end up with a module missing > something, without any error message. Err. There's a call to PyErr_Occurred() after the init function is called, so you should get an error message. Carrying on regardless after an error runs the risk that the exception will be cleared, of course. > What would be the correct thing to do - I assume something like > > if (PyModule_AddIntConstant(m, "MAX_WBITS", MAX_WBITS)) { > PyErr_Print(); > return; > } Just return, I think. Cheers, mwh -- The meaning of "brunch" is as yet undefined. -- Simon Booth, 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 310 and exceptions
On Fri, Apr 22, 2005 at 19:03 -0700, Josiah Carlson wrote: > [EMAIL PROTECTED] (holger krekel) wrote: > > basically translates to: > > > > if hasattr(x, '__enter__'): > > x.__enter__() > > try: > > ... > > except: > > if hasattr(x, '__except__'): x.__except__(...) > > else: x.__exit__() > > else: > > x.__exit__() > > Nope... > > >>> def foo(): > ... try: > ... print 1 > ... return > ... except: > ... print 2 > ... else: > ... print 3 > ... > >>> foo() > 1 > >>> doh! of course, you are right. So it indeeds better translates to a nested try-finally/try-except when transformed to python code. Nick Coghlan points at the correct ideas below in this thread. At the time i was implementing things by modifying ceval.c rather than by just a compiling addition, i have to admit. cheers, holger ___ 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 310 and exceptions
On Sat, Apr 23, 2005, Nick Coghlan wrote: > > In light of Alex's comments, I'd actually like to suggest the below as a > potential new definition for PEP 310 (making __exit__ optional, and adding > an __else__ handler): > > if hasattr(x, '__enter__'): > x.__enter__() > try: > try: > # Contents of 'with' block > except: > if hasattr(x, '__except__'): > if not x.__except__(*sys.exc_info()): # [1] > raise > else: > raise > else: > if hasattr(x, '__else__'): > x.__else__() > finally: > if hasattr(x, '__exit__'): > x.__exit__() +1, but prior to reading this post I was thinking along similar lines with your __exit__ named __finally__ and your __else__ named __exit__. My reasoning for that is that most of the time, people want their exit condition aborted if an exception is raised; having the "normal" exit routine called __else__ would be confusing except to people who do lots of exception handling. (I'm a bit sensitive to that right now; this week I wasted an hour because I didn't understand exceptions as well as I thought I did, although it was related more to the precise mechanics of raising and catching exceptions. Perhaps I'll submit a doc bug; I didn't find this explained in _Learning Python_ or Nutshell...) -- Aahz ([EMAIL PROTECTED]) <*> http://www.pythoncraft.com/ "It's 106 miles to Chicago. We have a full tank of gas, a half-pack of cigarettes, it's dark, and we're wearing sunglasses." "Hit it." ___ 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
__except__ use cases (was: Re: [Python-Dev] PEP 310 and exceptions)
On Sat, Apr 23, 2005 at 13:41 +1000, Nick Coghlan wrote: > Nick Coghlan wrote: > In light of Alex's comments, I'd actually like to suggest the below as a > potential new definition for PEP 310 (making __exit__ optional, and adding > an __else__ handler): > > if hasattr(x, '__enter__'): > x.__enter__() > try: > try: > # Contents of 'with' block > except: > if hasattr(x, '__except__'): > if not x.__except__(*sys.exc_info()): # [1] > raise On a side note, I don't see too much point in having __except__ return something when it is otherwise easy to say: def __except__(self, typ, val, tb): self.abort_transaction() raise typ, val, tb But actually i'd like to to mention some other than transaction-use cases for __except__, for example with class MyObject: def __except__(self, typ, val, tb): if isinstance(val, KeyboardInterrupt): raise # process exception and swallow it you can use it like: x = MyObject(): # do some long running stuff and MyObject() can handle internal problems appropriately and present clean Exceptions to the outside without changing the "calling side". With my implementation i also played with little things like: def __getattr__(self, name): Key2AttributeError: return self._cache[key] ... with an obvious __except__() implementation for Key2AttributeError. Similar to what Alex points out i generally think that being able to define API/object specific exception handling in *one* place is a great thing. I am willing to help with the PEP and implementation, btw. cheers, holger ___ 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 310 and exceptions
At 01:41 PM 4/23/05 +1000, Nick Coghlan wrote: Whichever way that point goes, this definition would allow PEP 310 to handle Alex's example of factoring out standardised exception handling, as well as the original use case of resource cleanup, and the transaction handling: class transaction(object): def __enter__(self): begin_transaction() def __except__(self, *exc_info): abort_transaction() def __else__(self): commit_transaction() I'd like to suggest '__success__' in place of '__else__' and '__before__'/'__after__' instead of '__enter__'/'__exit__', if you do take this approach, so that what they do is a bit more obvious. ___ 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 310 and exceptions
Nick Coghlan <[EMAIL PROTECTED]> writes: > holger krekel wrote: >> Moreover, i think that there are more than the "transactional" >> use cases mentioned in the PEP. For example, a handler may want to >> log exceptions to some tracing utility or it may want to swallow >> certain exceptions when >> its block does IO operations that are ok to fail. > > With the current PEP 310 definition, these can be manually handled using > sys.exc_info() in the __exit__ method. With the proposed implementation of PEP 310 rev. 1.5 it wouldn't work. sys.exc_info returns a tuple of Nones unless an except: clause has been entered. Either sys.exc_info() would have to be changed to always return exception information after an exception has been raised or the implementation would have to be changed to do the equivalent of e.g. if hasattr(var, "__enter__"): var.__enter__() try: try: suite except: pass finally: var.__exit__() An empty except: suite suffices. In C that's equivalent to a call to PyErr_NormalizeException AFAICT. Bernhard -- Intevation GmbH http://intevation.de/ Skencil http://skencil.org/ Thuban http://thuban.intevation.org/ ___ 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 310 and exceptions
Bernhard Herzog wrote: With the proposed implementation of PEP 310 rev. 1.5 it wouldn't work. sys.exc_info returns a tuple of Nones unless an except: clause has been entered. Either sys.exc_info() would have to be changed to always return exception information after an exception has been raised or the implementation would have to be changed to do the equivalent of e.g. Interesting. Although the 'null' except block should probably be a bare 'raise', rather than a 'pass': Py> try: ... try: ... raise TypeError("I'm an error!") ... except: ... raise ... finally: ... print sys.exc_info() ... (, , ) Traceback (most recent call last): File "", line 3, in ? TypeError: I'm an error! All the more reason to consider switching to a nested try/finally + try/except/else definition for 'with' blocks, I guess. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ 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 310 and exceptions
Aahz wrote: On Sat, Apr 23, 2005, Nick Coghlan wrote: In light of Alex's comments, I'd actually like to suggest the below as a potential new definition for PEP 310 (making __exit__ optional, and adding an __else__ handler): if hasattr(x, '__enter__'): x.__enter__() try: try: # Contents of 'with' block except: if hasattr(x, '__except__'): if not x.__except__(*sys.exc_info()): # [1] raise else: raise else: if hasattr(x, '__else__'): x.__else__() finally: if hasattr(x, '__exit__'): x.__exit__() +1, but prior to reading this post I was thinking along similar lines with your __exit__ named __finally__ and your __else__ named __exit__. My reasoning for that is that most of the time, people want their exit condition aborted if an exception is raised; having the "normal" exit routine called __else__ would be confusing except to people who do lots of exception handling. In the original motivating use cases (file handles, synchronisation objects), the resource release is desired unconditionally. The aim is to achieve something similar to C++ scope-delimited objects (which release their resources unconditionally as the scope is exited). This parallel is also probably the source of the names of the two basic functions ('enter'ing the contained block, 'exit'ing the contained block). So, I think try/finally is the right semantics for the basic __enter__/__exit__ use case (consider that PEP 310 is seen as possibly worthwhile with *only* these semantics!). For error logging type use cases, only the exception handling is required. The issue of a 'no exception raised' handler only comes up for cases like transactions, where the commit operation is conditional on no exception being triggered. I understand you agree that, for those cases, the best spot to call the handler is an else clause on the inner try/except block. That way, it is skipped by default if an exception goes off, but the exception handling method can still invoke the method directly if desired (e.g. an exception is determined to be 'harmless'. However, I do agree with you that the use of '__else__' as a name is exposing too much of the underlying implementation (i.e. you need to understand the implementation for the name to make sense). I think renaming '__exit_' to '__finally__' would be a similar error, though. Which means finding a different name for '__else__'. Two possibilities that occur to me are '__ok__' or '__no_except__'. The latter makes a fair amount of sense, since I can't think of a way to refer to the thing other than as a 'no exception' handler. Cheers, Nick. P.S. I'm ignoring my housemate's suggestion of '__accept__' for the no-exception handler :) -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ 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
[Python-Dev] Re: __except__ use cases
holger krekel wrote: On a side note, I don't see too much point in having __except__ return something when it is otherwise easy to say: def __except__(self, typ, val, tb): self.abort_transaction() raise typ, val, tb It has to do with "Errors should never pass silently, unless explicitly silenced". Consider: def __except__(self, typ, val, tb): self.abort_transaction() With __except__ returning a value, the implicit 'return None' means that the exception is propagated by default. Without the 'suppress exception' boolean return value, this naive handler would not only abort the transaction, but swallow each and every exception that occured inside the 'with' block. Another common error with a manual reraise would involve not including the traceback properly, leading to difficulties with debugging. IOW, returning a value from __except__ should make the exception handlers cleaner, and easier to 'do right' (since reraising simply means returning a value that evaluates to False, or falling off the end of the function). Suppressing the exception would require actively adding 'return True' to the end of the handler. But actually i'd like to to mention some other than transaction-use cases for __except__, for example with class MyObject: def __except__(self, typ, val, tb): if isinstance(val, KeyboardInterrupt): raise # process exception and swallow it s/raise/return True/ for the return value version. def __getattr__(self, name): Key2AttributeError: return self._cache[key] ... with an obvious __except__() implementation for Key2AttributeError. Seeing this example has convinced me of something. PEP 310 should use the 'with' keyword, and 'expression block' syntax should be used to denote the 'default object' semantics proposed for Python 3K. For example: class Key2AttributeError(object): def __init__(self, obj, attr): self: .obj_type = type(obj) .attr = attr def __except__(self, ex_type, ex_val, ex_tb): if isinstance(ex_type, KeyError): self: raise AttributeError("%s instance has no attribute %s" % (.obj_type, .attr)) # Somewhere else. . . def __getattr__(self, name): with Key2AttributeError(self, key): self: return ._cache[key] Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ 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 310 and exceptions
Nick Coghlan wrote: > Which means finding a different name for '__else__'. Two possibilities > that occur to me are '__ok__' or '__no_except__'. The latter makes a > fair amount of sense, since I can't think of a way to refer to the thing > other than as a 'no exception' handler. While we're on the subject of block handler method names, do the method names need four underscores? 'enter' and 'exit' look better than '__enter__' and '__exit__'. 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 310 and exceptions
Shane Hathaway wrote: Nick Coghlan wrote: Which means finding a different name for '__else__'. Two possibilities that occur to me are '__ok__' or '__no_except__'. The latter makes a fair amount of sense, since I can't think of a way to refer to the thing other than as a 'no exception' handler. While we're on the subject of block handler method names, do the method names need four underscores? 'enter' and 'exit' look better than '__enter__' and '__exit__'. It's traditional for slots (or pseudo-slots) to have magic method names. It implies that the methods are expected to be called implicitly via special syntax or builtin functions, rather than explicitly in a normal method call. The only exception I can think of is the 'next' method of the iterator protocol. That method is often called explicitly, so the exception makes sense. For resources, there doesn't seem to be any real reason to call the methods directly - the calls will generally be hidden behind the 'with' block syntax. Hence, magic methods. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ 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