2

Simple: I have an Python object id, and I want to check if there is an object with that id.

From this SO answer, you can get an existing object by id with

import ctypes
a = 10
object_id = id(a)
ctypes.cast(object_id, ctypes.py_object).value

But it hangs when called with a arbitrary object_id, so that's an impractical solution.

Community
  • 1
  • 1
jmilloy
  • 7,875
  • 11
  • 53
  • 86

1 Answers1

2

To do this, you'd need an exhaustive enumeration of all Python objects. Otherwise, it's impossible to tell the difference between an object and a memory region that just happens to look like an object.

Unfortunately, there isn't such an exhaustive list. The closest thing is probably gc.get_objects(), which returns a list of all objects tracked by the garbage collector (excluding the list itself). You could search that for an object matching your ID, but things like x = 1; print x in gc.get_objects() won't find the object.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Yeah that makes sense. It's an object that isn't in gc.get_objects that I'm interested in. Why isn't it being tracked!? Thanks. – jmilloy Dec 03 '15 at 22:04
  • 1
    @jmilloy: `1` is untracked because it can't possibly participate in a reference cycle. Whatever object you're trying to find, either it's untracked because Python knows it can't be in a reference cycle, or it's already been collected. – user2357112 Dec 03 '15 at 22:06
  • The object I'm interested in is a numpy array that's an attribute of a class. When the attribute is assigned to a new object, it seems that the old object never goes away. – jmilloy Dec 03 '15 at 22:08
  • @jmilloy: Why are you trying to do this, anyway? Wouldn't a weakref or an actual reference be more useful than the ID? – user2357112 Dec 03 '15 at 22:10
  • I still don't entirely understand when and why this object is getting collected, or the effect that gc.collect is having on the total memory usage of the process (none). But in the process I got curious. I don't actually need an answer to the question to solve the issue. – jmilloy Dec 03 '15 at 22:14
  • 1
    @jmilloy, in CPython an object is deallocated when its reference count goes to 0. You can check the reference count via `sys.getrefcount(obj) - 1` (minus 1 for the call stack reference). How this affects available memory is a complex subject. It depends on the size of the object, the operating system, the allocator configuration (e.g. glibc `mallopt` options `M_MMAP_THRESHOLD` and `M_TRIM_THRESHOLD`), and a high-water mark effect resulting from the fact that CPython objects never move in memory, which can prevent the heap from shrinking. – Eryk Sun Dec 04 '15 at 12:46
  • @eryksun Thanks, that's really helpful. I was too fixated on the gc module. – jmilloy Dec 04 '15 at 14:56