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 = 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)