does python have useless destructors?

Robert Brewer fumanchu at amor.org
Thu Jun 10 11:27:17 EDT 2004


Duncan Booth wrote:
> Apparently the next release of Microsoft's C++ for managed 
> environments 
> will handle the issue in quite a nice way. They will let you declare 
> managed heap based objects as though they are on the stack, 
> and if the 
> object supports their dispose pattern the compiler 
> automatically inserts 
> the required try..finally block. Python might need an extra 
> keyword, but 
> perhaps it could benefit from something similar.
> 
> e.g.
> 
> def f(filename):
>    dispose infile, outfile
> 
>    infile = file(filename, "r")
>    outfile = file(filename+".out", "w")
>    outfile.write(infile.read())
> 
> would be equivalent to something like:
> 
> def f(filename):
>    try:
>       infile = file(filename, "r")
>       outfile = file(filename+".out", "w")
>       outfile.write(infile.read())
>    finally:
>       _inexception = sys.exc_info()[0] is not None
>       for _temp in ['outfile', 'infile']:
>           if _temp in locals():
>               try:
>                   locals()[_temp].__dispose__()
>               except:
>                   pass
>       if not _inexception and sys.exc_info()[0] is not None:
>           raise
> 
> Obviously the keyword might be something other than dispose, 
> and the method 
> called to dispose of the object might have a different name. 
> Plus I'm not 
> sure I got the logic right on what the equivalent code should 
> be (which I 
> think is an argument *for* a scheme such as this). It should 
> be ignoring 
> variables which aren't yet set, and preserving the original 
> exception if 
> there is one, but if any __dispose__ throws an exception that 
> should be 
> propogated while not preventing all other __dispose__ methods 
> also being 
> called.

AFAICT, you don't need to reraise the exception. Example:

>>> try:
... 	f
... finally:
... 	print 'finally'
... 	
finally
Traceback (most recent call last):
  File "<interactive input>", line 2, in ?
NameError: name 'f' is not defined


But I could be wrong--perhaps you've got a requirement I can't see on
first glance. Given that, perhaps we can simplify your example to:

def f(filename):
    try:
        infile = file(filename, "r")
        outfile = file(filename+".out", "w")
        outfile.write(infile.read())
    finally:
        for _temp in ['outfile', 'infile']:
            if _temp in locals():
                try:
                    locals()[_temp].__dispose__()
                except:
                    pass

...which could be rewritten as (totally untested)...

def dispose(localdict, argnames):
    for name in argnames:
        obj = localdict.get(name)
        if obj:
            try:
                dispfunc = obj.__dispose__
            except AttributeError:
                pass
            else:
                dispfunc()

def f(filename):
    try:
        infile = file(filename, "r")
        outfile = file(filename+".out", "w")
        outfile.write(infile.read())
    finally:
        dispose(locals(), 'infile', 'outfile')


Write dispose once and drop it somewhere accessible in my site...a
rather convenient idiom. Thanks! I think I'll pursue it.


Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org




More information about the Python-list mailing list