Of the three choices my bet is that you're doing it wrong in that your o object is the lamp object, not the data part, or some other non LAMP data object.
import bpy
context = bpy.context
#o = bpy.data.objects.get("Lamp") # assumes you have an ob named Lamp
#o.data = bpy.data.lamps.get("Lamp")
o = context.active_object
if o:
#o.energy
print("%s (%s)" % (o.name, o.type), getattr(o, "energy", "Has NO energy property"))
o = o.data
#o.data.energy
if o:
print("%s (%s)" % (o.name, o.type), getattr(o, "energy", "Has NO energy property"))
If you grab a datapath from the DATA Properties panel, eg mesh panel for mesh objects, the datapath will be resolvable on the data part.
context.active_object.data
(except for empties, whose data part is None)