How to give object away to python garbage collection?
Asked Answered
M

4

15

There are several threads on Python garbage collection in SO, and after reading about five, plus some doc on line, i am still not sure as to how garbage collection works and how i should manage objects which i am not using. In fact somewhere i read one should not do anything about collecting garbage, others tell one should del objects, while others again explain de-referencing an object is enough for Python to collect it as garbage.

So, at the risk of creating a duplicate, i will ask the question again, but differently, hoping to get more comprehensive and clearer information.

In my case i want to make a small simulation with objects representing people. Several instances of the Person() class will be created. It should exist for some time until it virtually "dies" while other instances will be created.

Now how do i make this Person() instance "die" (assuming many many of these instances will be created and i don't want these instances to hang out like ghosts)?

There are several ways i can reference an object:

john = Person('john')

or

people = []
people.append(Person('john'))

or

people = {}
people['john'] = Person('john')

What is the best way to keep my program clean, freeing resources optimally? And what is the best way then to reference my object so i can control the deletion of the object?

Musca answered 11/6, 2011 at 9:57 Comment(3)
Check the gc module: docs.python.org/library/gc.htmlChas
The short answer is: You don't. It takes it itself when you don't use (have a reference to) it any more. Or perhaps later or never. GC is not deterministic, the only guarantee is that you won't run out of memory if there's garbage to be reused (except in some circumstances with conservative GCs, but neither Python nor in any other memory-managed language has to use these; only languages with pointer arithmetic or a way for pointers to escape as integers etc. need those). And unless you understand that and why you usually don't need to worry at all, you should leave it at that.Sashasashay
This question could equally apply to ruby, Smalltalk, Java, C# or VB6 and perhaps many others.Annetteannex
A
7

I find that most programs create and dispose of objects quite naturally, so I never normally worry about it.

Some examples:

person = Person('john')
person = Person('james')
# Whoops! 'john' has died!

people = []
people.append(Person('john'))
# ...
# All 'Persons' live in people
people = []
# Now all 'Persons' are dead (including the list that referenced them)

class House():
    def setOwner(self, person):
        self.owner = person

house.setOwner(people[0])
# Now a House refers to a Person
people = []
# Now all 'Persons' are dead, except the one that house.owner refers to.

What I assume you are after is this:

people = {}
people['john'] = Person('john')

def removePerson(personName):
    del people[personName]

removePerson('john')

In this case people is the master list and you can control when a Person gets added and removed from the list (its a dictionary).

You may have to think through the concept of a person being created and then dying very thoroughly: Once created how does the person first interact with the simulation. Upon death, how should you untangle the references? (Its ok for a person to refer to other stuff, its things like House in my example that would keep a person alive. You could have other objects hold on to just the name of the person).

Annetteannex answered 11/6, 2011 at 11:7 Comment(0)
L
12

Maybe this also can help:

>>> # Create a simple object with a verbose __del__ to track gc.
>>> class C:
...     def __del__(self):
...         print "delete object"
... 
>>> c = C()
>>> # Delete the object c successfully.
>>> del c
delete object
>>> # Deletion of an object when it go out of the scope where it was defined.
>>> def f():
...     c = C()
...
>>> f()
delete object
>>> c = C()
>>> # Create another reference of the object.
>>> b = c
>>> # The object wasn't destructed the call of del only decremented the object reference. 
>>> del c
>>> # Now the reference counter of the object reach 0 so the __del__ was called. 
>>> del b
delete object
>>> # Create now a list that hold all the objects.
>>> l = [C(), C()]
>>> del l
delete object
delete object
>>> # Create an object that have a cyclic reference.
>>> class C:
...     def __init__(self):
...         self.x = self
...     def __del__(self):
...         print "delete object"
... 
>>> c = C()
>>> # Run the garbage collector to collect object.
>>> gc.collect()
9
>>> # the gc.garbage contain object that the gc found unreachable and could not be freed.  
>>> gc.garbage
[<__main__.C instance at 0x7ff588d84368>]
>>> # Break the cyclic reference.
>>> c.x = None
>>> # And now we can collect this object.
>>> del c
delete object
>>> # Create another object with cyclic reference.
>>> c = C()
>>> # When closing the interactive python interpreter the object will be collected.
delete object

Refrences : del method ; gc module ; weakref module

Lanctot answered 11/6, 2011 at 11:34 Comment(2)
Thanks :) all answers were really good, i picked up Quamrana's because he gave an answer that was more consistent with the question's example.Musca
@Benjamin: Glad you get your answer :)Lanctot
Q
9

None of this really has anything to do with garbage collection.

Python's main method of memory management uses reference counting.

In all cases above, Python keeps a count of all the references to the object, and when there are none left, the object is deleted (similar to std::shared_pointer in C++).

References get decreased when

  1. the object holding them is either explicitly deleted (via del)
  2. or goes out of scope (see also here (esp. ex. 8)).

In your case, this applies to either the john object, or either of the people containers. They go out of scope at the end of the function that created them (assuming they are not returned to the calling function). The vast majority of the time, you can just let them go out of scope - it's only when you create really heavy objects or collections - say inside a big loop - that you might want to consider explicitly using del.

Garbage collection really only comes into play when there are reference cycles - for instance, when an object refers to itself. Like:

a = []
a.append(a)

Again, this happens automatically, and you shouldn't need to do anything special.

Quadri answered 11/6, 2011 at 10:53 Comment(1)
Thanks :) all answers were really good, i picked up Quamrana's because he gave an answer that was more consistent with the question's example.Musca
A
7

I find that most programs create and dispose of objects quite naturally, so I never normally worry about it.

Some examples:

person = Person('john')
person = Person('james')
# Whoops! 'john' has died!

people = []
people.append(Person('john'))
# ...
# All 'Persons' live in people
people = []
# Now all 'Persons' are dead (including the list that referenced them)

class House():
    def setOwner(self, person):
        self.owner = person

house.setOwner(people[0])
# Now a House refers to a Person
people = []
# Now all 'Persons' are dead, except the one that house.owner refers to.

What I assume you are after is this:

people = {}
people['john'] = Person('john')

def removePerson(personName):
    del people[personName]

removePerson('john')

In this case people is the master list and you can control when a Person gets added and removed from the list (its a dictionary).

You may have to think through the concept of a person being created and then dying very thoroughly: Once created how does the person first interact with the simulation. Upon death, how should you untangle the references? (Its ok for a person to refer to other stuff, its things like House in my example that would keep a person alive. You could have other objects hold on to just the name of the person).

Annetteannex answered 11/6, 2011 at 11:7 Comment(0)
S
2

Previous answers are correct but here is what is recommended according to python 3.7 Document:

"Python does automatic memory management (reference counting for most objects and garbage collection to eliminate cycles). The memory is freed shortly after the last reference to it has been eliminated."

If you really have to do this because of memory management issues you are experiencing with a particular case then import the gc library and just do this

     del self.someInstanceOfyourClass
             gc.collect()

here is a simple example https://github.com/nanoseconds/PythonTest/blob/master/test.py

Sooksoon answered 9/10, 2018 at 20:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.