Tempfiles created by tmpfile removed at exit - can I change this easily?

Hi, I think the subject says it all, really. I'm trying to debug a script
(I think I'd call it a script as it is replacing a bash script), and if I
give -d as an argument to the script, then I'd like the tempfile not to be
deleted on exit. Will I have to override the close method in tmpfile, or
is there an easier way, please?

Thanks
Graham Nicholls

···

--
The answer's always "Yes". Now, what's the question?

"Graham Nicholls" <graham@rockcons._ns_co.uk(spam_filtered)> schrieb im
Newsbeitrag news:416bcf5a$0$1555$afc38c87@auth.uk.news.easynet.net...

Hi, I think the subject says it all, really. I'm trying to debug a

script

(I think I'd call it a script as it is replacing a bash script), and if

I

give -d as an argument to the script, then I'd like the tempfile not to

be

deleted on exit. Will I have to override the close method in tmpfile,

or

is there an easier way, please?

Thanks
Graham Nicholls
--

The answer's always "Yes". Now, what's the question?

No, serious: overriding Tempfile#close won't help as that has no impact on
the file deletion. If it's just for debugging, you can just copy the temp
dir contents before the script terminates.

Alternatively you can try ObjectSpace.undefine_finalizer(tempfile) to
prevent deletion. I didn't test this, just looked at the source. But
chances are good that it works. :slight_smile:

Kind regards

    robert

i would try not to mess with the interals of Tempfile (although you could
easily do it that way) and make a subclass with this behaviour, eg:

   harp:~ > cat a.rb
   require 'tempfile'

   class Tmpfile < Tempfile
     class << self; attr :litter, true; end
     def initialize(*a,&b)
       t = super
       ObjectSpace::undefine_finalizer self if self.class.litter
       t
     end
   end

   Tmpfile::litter = ENV['DEBUG']
   t = Tmpfile::new __FILE__
   puts t.path

   harp:~ > ruby a.rb
   /tmp/a.rb11653.0

   harp:~ > ls /tmp/a.rb11653.0
   ls: /tmp/a.rb11653.0: No such file or directory

   harp:~ > DEBUG=1 ruby a.rb
   /tmp/a.rb11655.0

   harp:~ > ls /tmp/a.rb11655.0
   /tmp/a.rb11655.0

whatever solution you choose - you must basically undefine the finalizer
somehow.

regards.

-a

···

On Tue, 12 Oct 2004, Graham Nicholls wrote:

Hi, I think the subject says it all, really. I'm trying to debug a script
(I think I'd call it a script as it is replacing a bash script), and if I
give -d as an argument to the script, then I'd like the tempfile not to be
deleted on exit. Will I have to override the close method in tmpfile, or is
there an easier way, please?

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

<Ara.T.Howard@noaa.gov> schrieb im Newsbeitrag
news:Pine.LNX.4.60.0410120806520.8667@harp.ngdc.noaa.gov...

> Hi, I think the subject says it all, really. I'm trying to debug a

script

> (I think I'd call it a script as it is replacing a bash script), and

if I

> give -d as an argument to the script, then I'd like the tempfile not

to be

> deleted on exit. Will I have to override the close method in tmpfile,

or is

> there an easier way, please?

i would try not to mess with the interals of Tempfile (although you

could

easily do it that way) and make a subclass with this behaviour, eg:

   harp:~ > cat a.rb
   require 'tempfile'

   class Tmpfile < Tempfile
     class << self; attr :litter, true; end
     def initialize(*a,&b)
       t = super
       ObjectSpace::undefine_finalizer self if self.class.litter
       t
     end
   end

What do you need that "t" for? IMHO it's completely superfluous. The
return value of initialize is always completely ignored.

Also from an aesthetical point of view, I'd expect the flag "litter" to
behave exactly the other way round: if litter is true throw it away; you
keep it if litter is true.

   Tmpfile::litter = ENV['DEBUG']
   t = Tmpfile::new __FILE__
   puts t.path

   harp:~ > ruby a.rb
   /tmp/a.rb11653.0

   harp:~ > ls /tmp/a.rb11653.0
   ls: /tmp/a.rb11653.0: No such file or directory

   harp:~ > DEBUG=1 ruby a.rb
   /tmp/a.rb11655.0

   harp:~ > ls /tmp/a.rb11655.0
   /tmp/a.rb11655.0

whatever solution you choose - you must basically undefine the finalizer
somehow.

Yep.

Regards

    robert

···

On Tue, 12 Oct 2004, Graham Nicholls wrote:

Robert Klemme wrote:

No, serious: overriding Tempfile#close won't help as that has no impact on
the file deletion. If it's just for debugging, you can just copy the temp
dir contents before the script terminates.

Alternatively you can try ObjectSpace.undefine_finalizer(tempfile) to
prevent deletion. I didn't test this, just looked at the source. But
chances are good that it works. :slight_smile:

Thanks - thats taught me about ObjectSpace, and finalizers, which presumably
run on object deletion, and hopefully it works, too!

Graham

···

--
The answer's always "Yes". Now, what's the question?

   require 'tempfile'

   class Tmpfile < Tempfile
     class << self; attr :litter, true; end
     def initialize(*a,&b)
       t = super
       ObjectSpace::undefine_finalizer self if self.class.litter
       t
     end
   end

What do you need that "t" for? IMHO it's completely superfluous.

i always use a clearly defined return value in my code as, at minimum,
doccumentation. when i glance at the above it's instantly clear to me (eg.
when re-reading this in six months) that i am doing nothing except removing
the finalizer from the instance and returning it. in general i find that the
magic ruby rule of returning value of the last statement bad to rely upon in
all but the most simply cases - but for the real reason see below:

The return value of initialize is always completely ignored.

that cannot be asserted:

   harp:~ > cat a.rb
   class A
     def initialize
       42
     end
     def reinit
       p initialize
     end
   end

   harp:~ > ruby a.rb
   42

if you mean to say that 'the value of initialize is ignored by default for the
single case when it is called by the default Object#new method' then you are
correct. remember, initialize is simply a method called, in one single case,
to fill in blank objects - it's quite possible and acceptable to call it with
side effects from within the class, or from within subclasses.

in general i think it's poor practice to leave a method with a random return
value: one should return something meaningful and, if that's not possible,
return self to allow chaining.

Also from an aesthetical point of view, I'd expect the flag "litter" to
behave exactly the other way round: if litter is true throw it away; you
keep it if litter is true.

tempfiles are thrown away 'properly' in the normal case - eg. they do not
'litter' /tmp (a very dangerous practice). i would consider a program that
did not clean up after itself to have 'littered' - but it's of no matter:
change it if you like.

cheers.

-a

···

On Tue, 12 Oct 2004, Robert Klemme wrote:
   A::new.reinit
--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

<Ara.T.Howard@noaa.gov> schrieb im Newsbeitrag
news:Pine.LNX.4.60.0410120828420.8667@harp.ngdc.noaa.gov...

>> require 'tempfile'
>>
>> class Tmpfile < Tempfile
>> class << self; attr :litter, true; end
>> def initialize(*a,&b)
>> t = super
>> ObjectSpace::undefine_finalizer self if self.class.litter
>> t
>> end
>> end
>
> What do you need that "t" for? IMHO it's completely superfluous.

i always use a clearly defined return value in my code as, at minimum,
doccumentation. when i glance at the above it's instantly clear to me

(eg.

when re-reading this in six months) that i am doing nothing except

removing

the finalizer from the instance and returning it.

Well, but since you don't know what Tempfile#initialize returns (it's not
documented AFAIK) you can't deal with it properly anyway, can you?

in general i find that the
magic ruby rule of returning value of the last statement bad to rely

upon in

all but the most simply cases - but for the real reason see below:

> The return value of initialize is always completely ignored.

that cannot be asserted:

   harp:~ > cat a.rb
   class A
     def initialize
       42
     end
     def reinit
       p initialize
     end
   end

   A::new.reinit

   harp:~ > ruby a.rb
   42

if you mean to say that 'the value of initialize is ignored by default

for the

single case when it is called by the default Object#new method' then you

are

correct. remember, initialize is simply a method called, in one single

case,

to fill in blank objects - it's quite possible and acceptable to call it

with

side effects from within the class, or from within subclasses.

Didn't think of that. But still as #initialize's return value is
generally *not* used I'd rather not rely on that value. In your example
I'd have defined reinit like this - in concordance with your other
statement about return values :slight_smile:

def reinit
  initialize
  self
end

in general i think it's poor practice to leave a method with a random

return

value: one should return something meaningful and, if that's not

possible,

return self to allow chaining.

Totally agree! Otherwise some internal state / instance might leak that
was never meant to be seen outside of the instance.

> Also from an aesthetical point of view, I'd expect the flag "litter"

to

> behave exactly the other way round: if litter is true throw it away;

you

> keep it if litter is true.

tempfiles are thrown away 'properly' in the normal case - eg. they do

not

'litter' /tmp (a very dangerous practice). i would consider a program

that

did not clean up after itself to have 'littered' - but it's of no

matter:

change it if you like.

Ah, ok *now* I understand how you meant it. Sorry for the noise.

Kind regards

    robert

···

On Tue, 12 Oct 2004, Robert Klemme wrote: