Lifetime of a local reference

Marko Rauhamaa marko at pacujo.net
Wed Feb 27 01:56:32 EST 2019


Alan Bawden <alan at csail.mit.edu>:

> Marko Rauhamaa <marko at pacujo.net> writes:
>>     def fun():
>>         f = open("lock")
>>         flock.flock(f, fcntl.LOCK_EX)
>>         do_stuff()
>>         sys.exit(0)
>> 
>> Question: can a compliant Python implementation close f (and,
>> consequently, release the file lock) before/while do_stuff() is
>> executed?
>
> A correct-but-fails-to-answer-your-real-question answer would be: "If
> you _care_ about when f gets closed, then just call f.close()
> yourself." So if you want to be _sure_ the lock stays locked while you
> "do stuff", you should write:
>
>    def fun():
>        f = open("lock")
>        flock.flock(f, fcntl.LOCK_EX)
>        do_stuff()
>        f.close()
>        sys.exit(0)
>
> And now you don't have to worry about the details of variable
> lifetimes.

Yes, although the operating system closes all files (and releases the
associated file locks) on process exit.

> But I appreciate that that isn't the true question that you wanted to ask!
> You are wondering if a Python implementation is _permitted_ to treat the
> code you wrote _as if_ you had written:
>
>    def fun():
>        f = open("lock")
>        flock.flock(f, fcntl.LOCK_EX)
>        del f
>        do_stuff()
>        sys.exit(0)
>
> which deletes the variable f from the local environment at a point where it
> will never be used again.  (Which could cause the lock to be released
> before do_stuff is even called.)
>
> This is an interesting question, and one that any garbage collected
> language should probably address somehow.  For example, the Java Language
> Specification contains the following language:
>
>    Optimizing transformations of a program can be designed that reduce the
>    number of objects that are reachable to be less than those which would
>    naively be considered reachable.  For example, a Java compiler or code
>    generator may choose to set a variable or parameter that will no longer be
>    used to null to cause the storage for such an object to be potentially
>    reclaimable sooner.
>
> (This is from section 12.6.1 of the Java 8 version, which is what I had
> handy.)

C compilers do similar things, which is why Guile documentation mentions
a special mechanism to prevent premature garbage collection:

   <URL: https://www.gnu.org/software/guile/docs/docs-2.0/guile-ref/Rememb
   ering-During-Operations.html>

> I suspect that given the history of Python, pretty much everybody has
> always assumed that a Python implementation will not delete local
> variables early. But I agree with you that the Python Language
> Reference does not appear to address this question anywhere!

Then there's the question of a sufficient way to prevent premature
garbage collection:

     def fun():
         f = open("lock")
         flock.flock(f, fcntl.LOCK_EX)
         do_stuff()
         f.close()
         sys.exit(0)

     def fun():
         f = open("lock")
         flock.flock(f, fcntl.LOCK_EX)
         do_stuff()
         f.close
         sys.exit(0)

     def fun():
         f = open("lock")
         flock.flock(f, fcntl.LOCK_EX)
         do_stuff()
         f
         sys.exit(0)

     def fun():
         f = open("lock")
         flock.flock(f, fcntl.LOCK_EX)
         do_stuff()
         sys.exit(0)


Marko


More information about the Python-list mailing list