1

I'm using Python as a wrapper to a library that, for desired reasons, keeps certain objects in memory until the process is killed and system GC removes them (or, a command is sent to explicitly remove them).

A user can retrieve references to one of these objects using a Python function, so I know when a user has accessed them, but I don't know when a user is done accessing them.

My question is: it is possible in Python to observe when a variable is deleted (for reasons of reassignment, going out of scope, garbage collection, etc.)? Can I observe state change on variables at all (similar to Swift's didSet/willSet)?

Daniel R. Livingston
  • 1,227
  • 14
  • 36
  • See [this answer](https://stackoverflow.com/questions/1481488/what-is-the-del-method-how-to-call-it/2452895#2452895) about the `__del__()` method. – martineau Mar 26 '19 at 01:58

1 Answers1

3

Python calls __del__ magic method when about to destroy an object.

You could override it and add your logic.

class ObserveDel:
    def __del__(self):
        # do your stuff

Or just replace it in place.

def _handle_del(obj):
    # do your stuff
a.__del__ = _handle_del
Pedro Rodrigues
  • 2,520
  • 2
  • 27
  • 26
  • This is not called when you use `del obj` though, only *if* that were the last reference – juanpa.arrivillaga Mar 26 '19 at 00:34
  • Correct, `del` decreases the reference counter. `__del__` is called when about to destroy the object from memory, ie.: after ref count reaches 0 (not necessarily immediately after) – Pedro Rodrigues Mar 26 '19 at 00:54
  • @martineau That is an overstatement. `__del__` will in fact be called at some point in time. There are nuances to keep in mind when dealing with `__del__` and they are clearly stated in the link I've provided to the [python's docs](https://docs.python.org/3/reference/datamodel.html#object.__del__). None of those is the possibility of `__del__` not being called. And you can be sure when is `__del__` will be called, it is clearly stated in the documentation: "Called when the instance is about to be destroyed". Not sure where you're trying to go with that comment. – Pedro Rodrigues Mar 26 '19 at 09:00
  • @PedroRodrigues: My understanding is that not everything is garbage collected when the program exits, and that when garbage collection occurs while the interpreter is running is totally unpredictable and that it doesn't necessary clean everything up. That's where I'm coming from. – martineau Mar 26 '19 at 09:11
  • @martineau That is more or less in line. The biggest 'gotcha' there is `__del__` is called during program destruction. Your program will most likely be in state where the `__del__` routine you created, just can't be executed (a lib we depend on maybe already destroyed, for example) combine that with the fact that exception will not be raised (but printed to stderror), so yes, it is naive to rely on the `__del__` method to execute properly. The gotchas are mostly contained in the interpreter exit phase. All of that is in python's docs. Not sure what you mean with the C++ reference. – Pedro Rodrigues Mar 26 '19 at 09:30
  • @PedroRodrigues: That comment, which was made under a different question, meant simply that just because those other languages work a certain way, doesn't mean Python does (or should). As for `__del__`, the only way to make sure and know it's called is by doing it manually i.e `del obj`, unfortunately even that happening can't be guaranteed. – martineau Mar 26 '19 at 09:44
  • @martineau Fair enough, if you feel my answer is incomplete (which I won't argue that it is) feel free to post a more complete one (I'll up vote you for that for sure, has I always do) if you feel it is in the scope of the question. I however do not think that is in the scope of the question. The `del` operator is a completely different game and has been addressed in a previous comment by @juanpa.arrivillaga, and does not guarantee that `__del__` is called at all, it merely decreases a number that tracks how many 'people' are interested in the object. – Pedro Rodrigues Mar 26 '19 at 09:48
  • @PedroRodrigues: I wasn't disparaging your answer, per se, just pointing out that writing code that counts on `__del__` being called generally isn't a good approach to use in Python (although it's fine in C++). – martineau Mar 26 '19 at 09:59
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190687/discussion-between-pedro-rodrigues-and-martineau). – Pedro Rodrigues Mar 26 '19 at 10:03