How to remove memory location that is referenced objects in python? - python

I want to remove all objects, which refer to one memory location. How to do it if I do not know their all name?
class Foo(object):
pass
class Bar(object):
pass
a = Foo()
b = a
c = Bar()
c.a_ref = a
c.b_ref = b
for item in a, b, c.a_ref, c.b_ref:
print(id(item))
""" Out:
140035270075472
140035270075472
140035270075472
140035270075472
"""
UPD:
Ok. I want to remove link or port1.link and don't worry about all the other ports(port2.link) linked to it, they also have to disappear.
class LINK(object):
pass
class PORT(object):
def __init__(self, link=None):
self.link = link
def __repr__(self):
return str(id(self.link))
link = LINK()
port1 = PORT()
port2 = PORT()
port1.link = port2.link = link
print(id(link), port1, port2)
# (140586778512720, 140586778512720, 140586778512720)
del link
print(port1, port2)
# (140586778512720, 140586778512720)
# want: (None, None) ???

You can't explicitly free memory in Python. The garbage collector is responsible to do that for you.
What you can do is guarantee that all the references to your objects are cleaned. The garbage collector works with epochs (like e1, e2 and e3) and only the objects in e3 will be cleaned in the next iteration.
Objects only go from epoch eX to eY (where Y > X) if there is no reference to them. So your objects start in e1; if you "clean" all references, in the next iteration of garbage collector they will be moved to e2; in the next one they will be moved to e3 and finally the memory will be released.
You can change the periodicity that garbage collector is called, but I would not recommend that. Or you can force the calling of garbage collector using gc.collect() but as I said, your objects have to go through all epochs before they are cleaned (that's why the calling of gc.collector() didn't work for you). Just to clarify, the garbage collector is called once a threshold (number of objects in memory tracked by the gc) is achieved.
If you want to do a diagnoses of memory leaks in Python you can also use the objgraph library which is really good. It builds graphs with all links and references between objects and let you identify cycles. Cycles are the main reason for the objects not to be released by the garbage collector when you think that all references are cleaned. Here is a good tutorial http://chase-seibert.github.io/blog/2013/08/03/diagnosing-memory-leaks-python.html

See the weakref module. It maintains a reference to an object without preventing it from being garbage collected if all its strong references are removed. Example:
import weakref
class LINK(object):
pass
class PORT(object):
def __init__(self, link=None):
if link is not None:
self.link = weakref.ref(link)
else:
self.link = None
def __repr__(self):
if self.link is None:
return 'None'
o = self.link()
return 'None' if o is None else str(id(o))
link = LINK()
port1 = PORT()
port2 = PORT()
port1.link = port2.link = weakref.ref(link)
print(id(link), port1, port2)
del link
print(port1, port2)
Output:
70741240 70741240 70741240
None None
Note, you may still have to call gc.collect() in some situations before the weak references report None.

You can't explicitly free memory. What you need to do is to make sure you don't keep references to objects. They will then be garbage collected, freeing the memory.
BTW, you can call gc.collect() to force a gc operation.
UPDATE:
You CAN NOT delete all the references to one object through only deleting one of its references, since you don't know who else is still using this object. And if so, there will be another question, how to prevent others to delete my object without acknowledging me.
I think best solution to your question is to delete attribute link separately.
del link
del port1.link
del port2.link
Then to get None after deleting, you should do this:
...
def __repr__(self):
repr_string = getattr(self, 'link', None)
return str(id(self.link)) if repr_string else None
...

Your real problem, to me, sounds like you have a graph where PORTs are nodes and LINKs are edges. And your requirement is that when you delete an edge, the two nodes that the edge connects should also be deleted. This can be done explicitly by overriding the __del__ method of the node so that deleting it deletes the edges which is connects to.
Python abstracts away the "memory" and using the fact that id gives you the memory location (which is really an implementation detail of CPython) is a flaky way of doing this.

Related

Deleting objects in memory using Python

I am trying this approach to delete an object in python. I read the documentation of Python stating that garbage collector will automatically delete the object that is not referenced.
def check():
class newOb():
def __init__(self,value):
self.value = value
print self.value
return None
class ob:
ins = {}
def cr(self,someuniqueid,value) :
newV = newOb(value)
ob.ins[someuniqueid] = newV ## saving this object refernce to the ob class ins dictionary
return newV
#### Accessing Object ###
someuniqueid = 12
c = ob()
d = c.cr(someuniqueid,123)
print d.value ## will print 123
# now deleting the associated object
del c.ins[someuniqueid]
check()
At the last step, I am removing the object reference from the memory
is using above procedure will delete the object from memory
If not then what is wrong with code and how to correct it
You would need to do del d as well, since d is also holding a reference to the same object. Calling del will only decrement the reference count and remove the particular reference from usage, but the actual in memory object is not garbage collected until the reference count hits 0.
I don't know what do you mean by writing:
If not then what is wrong with code and how to correct it
When you use del statement you delete a reference to an object. It will use up memory untill garbage collector is invoked. Remember that this can be a time-consuming process and not necessary if the process has enough memory to continue executing.
Generally speaking Python does not perform C++-like destructor bahaviour.
A quote from "Expert Python Programming":
The approach of such a memory manager is roughly based on a simple
statement: If a given object is not referenced anymore, it is removed.
In other words, all local references in a function are removed after
the interpreter:
• Leaves the function
• Makes sure the object is not being used anymore.
Under normal conditions, the collector will do a
nice job. But a del call can be used to help the garbage collector by
manually removing the references to an object manually.
So you don't manage memory by hand. You can help garbage collector, but it's better to leave memory managment behind the scenes.

Remove root from k-d-Tree in Python

For someone who is new to python, I don't understand how to remove an instance of a class from inside a recursive function.
Consider this code of a k-d Tree:
def remove(self, bin, targetAxis=0, parent=None):
if not self:
return None
elif self.data.x == bin.x and self.data.y == bin.y:
if self.rightNode:
self.data = self.rightNode.findMin((targetAxis+1)% KdSearch.DIMENSION)
self.rightNode = self.rightNode.remove(self.data, (targetAxis+1)% KdSearch.DIMENSION,self)
elif self.leftNode:
self.data = self.leftNode.findMin((targetAxis+1)% KdSearch.DIMENSION)
self.rightNode = self.leftNode.remove(self.data, (targetAxis+1)% KdSearch.DIMENSION,self)
else:
if not parent is None:
#get direction if child....
if not parent.leftNode is None:
if parent.leftNode.data.x == bin.x and parent.leftNode.data.y == bin.y:
parent.leftNode=None
if not parent.rightNode is None:
if parent.rightNode.data.x == bin.x and parent.rightNode.data.y == bin.y:
parent.rightNode=None
else:
print("Trying to delete self")
del self.data
del self.leftNode
del self.rightNode
del self.splittingAxis
else:
axis = self.splittingAxis % KdSearch.DIMENSION
if axis==0:
if bin.x <= self.data.x :
if self.leftNode:
self.leftNode.remove(bin,(targetAxis+1)% KdSearch.DIMENSION,self)
else:
if self.rightNode:
self.rightNode.remove(bin,(targetAxis+1)% KdSearch.DIMENSION,self)
else:
if bin.y <= self.data.y:
if self.leftNode:
self.leftNode.remove(bin,(targetAxis+1)% KdSearch.DIMENSION,self)
else:
if self.rightNode:
self.rightNode.remove(bin,(targetAxis+1)% KdSearch.DIMENSION,self)
The important part is this:
del self.data
del self.leftNode
del self.rightNode
del self.splittingAxis
How can i delete the current instance?
The del self or self=None or my approach is NOT working
What you're trying to do doesn't make sense in words, let alone in Python. What you want to do is remove the node from the tree. However, you don't have a tree object, you only have nodes. So how can you remove the node from the tree when there is no tree to remove it from?
Being generous, you could argue that you're implementing the tree without an explicit tree class by saying that a collection of nodes is a tree. But then you have the problem, what does an empty tree look like? Also, the client of the tree needs a reference to the tree (so it can add and remove nodes), but since you don't have a tree object, it can only have a reference to a node. Therefore, the client is the only one with the capability of emptying the tree, which it must do by deleting its reference to the node. It is not possible for an object in Python to remove arbitrary references to itself from other objects without knowledge of those objects, so your root node cannot generally delete itself from the "tree", which would mean deleting the reference to the node the client holds. To implement this would require a defined interface between the root node and the client, so when the client says "delete this node" the root node can reply and say "that's actually me, so delete me and you've got an empty tree". But this would be a pain.
Also, an implicit conceptual tree that is a collection of nodes goes against the Zen of Python:
Explicit is better than implicit.
So what I suggest is that you implement an explicit simple tree class that can be empty and that your client can hold a reference to. If you make it look a bit like a node, it can just be the parent of the root node and as far as the root node is concerned it (the root node) is a normal sub-node. Something like (caveat: not tested, and assuming the remove() function above is really a method on a node class):
class Tree:
def __init__(self):
self.leftNode = None
# need a rightNode to look like a node, but otherwise unused.
self.rightNode = None
# This will probably be useful.
#property
def isEmpty(self):
return self.leftNode is None
def addNode(self, node):
if self.leftNode is not None:
self.leftNode = node
return
self.leftNode.add(node, parent=self)
def removeNode(self, node):
# the node will remove itself from us, the parent, if needed
self.leftNode.remove(node, parent=self)
Then the client does things like:
tree = Tree()
tree.isEmpty
tree.addNode(node)
tree.removeNode(node)
Before looking at Python, consider the following C/C++ code:
struct A {
virtual void suicide() {
delete this;
}
};
int main() {
A* a = new A();
a->suicide();
return 0;
}
First, an object of type A is explicitly created. This boils down to allocating and initializing a small piece of memory (the only thing stored in the object is a pointer to the suicide function) and setting the variable a to point to that piece of memory.
Next, the suicide function is called, which internally asks the runtime to release the memory for the object by calling delete this. This is a totally valid operation, although it is not something you would normally do in real-life code. Namely, that after a->suicide() is called, the pointer a becomes invalid, because the memory it continues to point to is no longer there. For example, if you tried calling a->suicide() again afterwards, you would get a segmentation fault (because in order to call a->suicide you need to look up the pointer to the method suicide in the memory pointed to by a, and this memory is no longer valid).
But meaningful or not, you really can destroy a C/C++ object (i.e., release its memory) from any place, including the object's own method (assuming it was created on the heap, of course).
Now let us go back to Python. In Python, the situation is different. Although you create objects explicitly in Python, just like you do in C/C++, you have no way of forcefully releasing their memory. All the memory is managed by the garbage collector, which keeps track of which objects are currently referenced, which are not, and cleans the unreachable ones at the moments it decides appropriate.
Although the Python statement del self may seem syntactically similar to delete this in C/C++, it is really something completely different. It is not an order to the memory manager to clean the memory. Instead, it simply removes the key self from the "local variables" dictionary. The corresponding value (i.e. the memory self was referencing) still remains suspended somewhere on the heap.
Of course, if no one else points to that memory, chances are the garbage collector will release it soon (although not even this is guaranteed because it really depends on the GC algorithm used), but as you did a del self, someone is still pointing at the memory, because that someone just invoked the method.
Consider a "literal translation" of the C/C++ code above into Python:
class A(object):
def suicide(self):
del self
a = A()
a.suicide()
It is also totally valid Python code, however del self here does nothing (except for prohibiting you to refer to self later along in the same method, because you deleted the variable from the scope).
As long as there exists a variable a pointing to the created object from somewhere, its memory will not be released. Just as the memory would not be released here, for example:
a = A()
b = a
del a
For better understanding I suggest you also compare the meaning of del d[key] in Python with delete d[key] in C/C++.

Python destructor basing on try/finally + yield?

I've been testing a dirty hack inspired by this http://docs.python.org/2/library/contextlib.html .
The main idea is to bring try/finally idea onto class level and get reliable and simple class destructor.
class Foo():
def __init__(self):
self.__res_mgr__ = self.__acquire_resources__()
self.__res_mgr__.next()
def __acquire_resources__(self):
try:
# Acquire some resources here
print "Initialize"
self.f = 1
yield
finally:
# Release the resources here
print "Releasing Resources"
self.f = 0
f = Foo()
print "testing resources"
print f.f
But it always gives me:
Initialize
testing resources
1
and never "Releasing Resources". I'm basing my hope on:
As of Python version 2.5, the yield statement is now allowed in the
try clause of a try ... finally construct. If the generator is not
resumed before it is finalized (by reaching a zero reference count or
by being garbage collected), the generator-iterator’s close() method
will be called, allowing any pending finally clauses to execute. Source link
But it seems when the class member is being garbage collected together with the class their ref counts don't decrease, so as a result generators close() and thus finally is never called. As for the second part of the quote
"or by being garbage collected"
I just don't know why it's not true. Any chance to make this utopia work? :)
BTW this works on module level:
def f():
try:
print "ack"
yield
finally:
print "release"
a = f()
a.next()
print "testing"
Output will be as I expect:
ack
testing
release
NOTE: In my task I'm not able to use WITH manager because I'm releasing the resource inside end_callback of the thread (it will be out of any WITH). So I wanted to get a reliable destructor for cases when callback won't be called for some reason
The problem you are having is caused by a reference cycle and an implicit __del__ defined on your generator (it's so implicit, CPython doesn't actually show __del__ when you introspect, because only the C level tp_del exists, no Python-visible __del__ is created). Basically, when a generator has a yield inside:
A try block, or equivalently
A with block
it has an implicit __del__-like implementation. On Python 3.3 and earlier, if a reference cycle contains an object whose class implements __del__ (technically, has tp_del in CPython), unless the cycle is manually broken, the cyclic garbage collector cannot clean it up, and just sticks it in gc.garbage (import gc to gain access), because it doesn't know which objects (if any) must be collected first to clean up "nicely".
Because your class's __acquire_resources__(self) contains a reference to the instance's self, you form a reference cycle:
self -> self.__res_mgr__ (generator object) -> generator frame (referencing locals which includes) -> self
Because of this reference cycle, and the fact that the generator has a try/finally in it (creating tp_del equivalent to __del__), the cycle is uncollectable, and your finally block never gets executed unless you manually advance self.__res_mgr__ (which defeats the whole purpose).
You experiment happens to display this problem automatically because the reference cycle is implicit/automatic, but any accidental reference cycle where an object in the cycle has a class with __del__ will trigger the same problem, so even if you just did:
class Foo():
def __init__(self):
# Acquire some resources here
print "Initialize"
self.f = 1
def __del__(self):
# Release the resources here
print "Releasing Resources"
self.f = 0
if the "resources" involved could conceivably lead to a reference cycle with an instance of Foo, you'd have the same problem.
The solution here is one or both of:
Make your class a context manager so users provide the information necessary for deterministic finalization (by using with blocks) as well as providing an explicit cleanup method (e.g. close) for when with blocks aren't feasible (part of another object's state that is cleaned up through its own resource management). This is also the only way to provide deterministic cleanup on most non-CPython interpreters where reference counting semantics have never been used (so all finalizers are called non-deterministically, if at all)
Move to Python 3.4 or higher, where PEP 442 resolves the issue with uncollectable cyclic garbage (it's technically still possible to produce such cycles on CPython, but only via third party extensions that continue to use tp_del instead of updating to use the tp_finalize slot that allows cyclic garbage to be cleaned properly). It's still non-deterministic cleanup (if a reference cycle exists, you're waiting on the cyclic gc to run, sometime), but it's possible, where pre-3.4, cyclic garbage of this sort could not be cleaned up at all.

Deleting certain instances of a class attribute

I am working with classes in Python for the first time and I need to loop through my class attributes and delete certain instances under certain conditions. The problem is that I cannot find any examples of deleting instances of certain attributes. To be a little more specific, my class is phone_bills and one of my attributes is minutes_used and the instance would be minutes used of a specific month. Well, sometimes I need to delete that one month or one instance.
I am starting to wonder if working with classes is wrong for this particular project.
Here is some of my code (where i make the class and then at the bottom where i try to deltete an instance.
class MeterBill:
'components of MeterBill'
def __init__(self,IDC,Name,StartD,End_D,Mdays,Cons): #Name,StartD,End_D,Mdays,Cons):
self.IDC = IDC #idc
self.Name= Name #name
self.StartD = StartD #startd
self.End_D = End_D #end_d
self.Mdays = Mdays #modays
self.Cons = Cons #cons
def __repr__(self):
return repr((self.IDC,self.Name,self.StartD,self.End_D,self.Mdays,self.Cons))
#there is some other code here to read in the data then
e=len(bills); startlen=e;s=0
row=0; daysthresh=38; count=0
while count < startlen:
for row in range(s,e):
count = 1+ count
if bills[row-1].Mdays < daysthresh and bills[row-1].IDC==bills[row].IDC:
print bills[row-1],#row-1,meter[row-1]
bills[row].Mdays = bills[row-1].Mdays+bills[row].Mdays
bills[row].Cons = bills[row-1].Cons+bills[row].Cons
bills[row].StartD=bills[row-1].StartD
#del mybills.minutes_used
#bills=MeterBill()
del bills[row-1].Cons
the last 3 lines is me trying to delte an instance of my class at row-1 (using code from Peter Downs post). I want to delete this one line. I want to delete 1 single instance of each attribute that i defined.
so if I could get that del bill[row-1].cons to work then i would do it for all the other attributes at row-1.
Note you have to scroll to the right ot see my if statement.
I am starting to wonder if working with classes is wrong for this particular project.
No, certainly not, no worries :)
Lets say we have the following class:
class PhoneBills(object):
def __init__(self, minutes_used):
self.minutes_used = minutes_used
Then you can delete the attribute minutes_used simply by:
mybills = PhoneBills()
del mybills.minutes_used
Which would remove the attribute from your object mybills. All lookups would result in an exception. I'm not sure that this is what you want. Probably just setting minutes_used to 0 or None would be a better approach?
Using an object in this case isn't a bad idea, as others have pointed out. However, you have to think about the problem just a little bit differently in order to get the best use of these objects.
If you have a phone_bills object, then we assume its only responsibility is to manage a phone bill. It could be for a single month, it could be for an entire year - there's enough context in the object name that it could do both.
If it's managing a month-to-month bill, then what's required is, at the end of every month, the minutes used is recalculated, meaning that the value for the used minutes at this current point is reset, not deleted.
Now, unless your assignment specifically calls for you to delete the end-of-month total, then you're best served with resetting the value. The way to do this with Python objects is simple:
phone_bills.minutes_used = 0
Deleting means dereferencing the object, till its referencecounter reaches 0, so the garabage collector may free the allocated space for that particular object and effectivly destroying/deleting it.
What you want to do is set the appropriate attribute to None. By doing so, you reduce the refcounter by 1.
To illustrate what I mean, try the following:
import sys
ref = 'a Random object'
print sys.getrefcount(ref), id(ref)
newlist = [ref]
print sys.getrefcount(newlist[0]), id(newlist[0])
ref = None
print sys.getrefcount(newlist[0]), id(newlist[0])
newlist[0] = None
after the last line you have no reference to the underlying object, the refounter reaches 0 and the object gets collected by the garbage collector.
You may also use the del statement to express your intend clearly in your sourecode. e.g.: del june but then you also remove the identifier june from your namespace. Don't shoot the messanger! ;-)
I am starting to wonder if working with classes is wrong for this
particular project.
I believe that they may be unnecessary.
Instead of a class, try using dictionaries.
You could write a helper function to populate them, and it's very easy to remove a key from a dictionary.
The only reason to use a class is if you need instance methods - is that true?
Event then, you could rewrite them as regular functions.
def createPhoneBill(minutes_used):
return {
"minutes_used":minutes_used,
# you could put more attributes here, just add them as arguments to the function
}
As an added bonus, default values are much easier. Also, you get to use the dictionary.get(attr_name, default_value) function now, too.
Here's what deletion would look like:
Deleting an attribute:
mybills = createPhoneBill(5000):
if mybills["minutes_used"] > 2000:
del mybills["minutes_used"]
Deleting an 'instance':
mybills = createPhoneBill(5000):
if mybills["minutes_used"] > 3000:
del mybills
In Python, you don't delete objects--you simply remove any references towards them and allow the garbage collector to reclaim the memory they're holding.
Assigning phone_bills_obj.minutes_used = None would cause the garbage collector to remove the object referenced by phone_bills_ojb.minutes_used, in case the same object isn't being referenced anywhere else.

How to give object away to python garbage collection?

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?
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
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
the object holding them is either explicitly deleted (via del)
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.
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).
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

Categories