Is it possible to safely and reliably maintain a reference to a blender object in python? I'd like to be able to refer to the same object multiple times from python. I'd ideally like to be able to move back and forth between using the python console and using the UI.

The official documentation appears to offer conflicting advice about how to maintain references to objects from python, on the "Gotchas" page. Under the heading "Data Names" we have the following:


  Its better practice not to reference objects by names at all, once created you can store the data in a list, dictionary, on a class etc, there is rarely a reason to have to keep searching for the same data by name.


This suggests keeping a reference to an object directly, rather than by name.

Further down the same page, under the heading "Help! My script crashes Blender", we have the following:


  Do not keep direct references to Blender data (of any kind) when modifying the container of that data, and/or when some undo/redo may happen (e.g. during modal operators execution…). Instead, use indices (or other data always stored by value in Python, like string keys…), that allow you to get access to the desired data.


And a little further down:


  As suggested above, simply not holding references to data when Blender is used interactively by the user is the only way to ensure the script doesn’t become unstable.


This suggests that keeping a reference to an object directly is unsafe if we'd like to work interactively, and we should instead refer to an object by name (I think this is what is meant by "string key") or by index. If I've understood correctly, the index of an object may change if other objects are removed, so accessing objects by index is also unreliable.

Is there a safe, reliable way to maintain a reference to an object, or is this just a pain point of the python API?
Use a PointerProperty

As pointed out in Is it possible to use bpy.props.PointerProperty to store a pointer to an object?  can point to any blender bpy.types.ID type object, in example adding an object_of_interest pointer to the scene.

import bpy
from bpy.props import PointerProperty


bpy.types.Scene.object_of_interest = PointerProperty(type=bpy.types.Object)


Run script above and test in python console below.

Starts off not set, None

&gt;&gt;&gt; C.scene.object_of_interest is None
True


Set it to the context object

&gt;&gt;&gt; C.scene.object_of_interest = C.object

&gt;&gt;&gt; C.scene.object_of_interest
bpy.data.objects['Cube']


Rename it

&gt;&gt;&gt; C.scene.object_of_interest.name = "Foogle"
&gt;&gt;&gt; C.scene.object_of_interest
bpy.data.objects['Foogle']

&gt;&gt;&gt; C.object
bpy.data.objects['Foogle']


Remove it

&gt;&gt;&gt; D.objects.remove(C.object)


Back to None

&gt;&gt;&gt; C.scene.object_of_interest is None
True


If we did this via reference ie

object_of_interest = C.object


deleting then re-referencing would mean death to blender.