How to find out if an object has an action with Python? How can I use Python to find out if all the selected objects have an action and do something then? If one or more of the selected objects don't have an action, I'd like to print an info/error message saying that "All the selected objects must have an action.".

It's easy to check if an object has shape keys or materials but Terminal says object of type 'Action' has no len()if I try to do this:

import bpy

o = bpy.context.object

if o.animation_data.action:
    num_of_actions = len( o.animation_data.action )
    print( "Number of actions: ", num_of_actions )


This helps a little bit but isn't the answer to my problem.

This is the best I can do (had some help from Jeremy for the logic bricks):

# This adds the logic bricks to objects that allow them to be playable in BGE, but only to the selected objects that have an action. Actionless objects are ignored.
# Credit goes mostly to Jeremy Behreandt

import bpy

frames_to_be_played = 9999

ops=bpy.ops
context=bpy.context

# Cache shortcuts.
ops_mesh = ops.mesh
ops_object = ops.object
ops_logic = ops.logic
scene = context.scene

selected = bpy.context.selected_objects

for obj in selected:
    ad = obj.animation_data
    if ad:
        if ad.action:
            bpy.context.scene.objects.active = obj

            current_object = context.active_object

            # Cache shortcut to cube's game engine.
            game_engine = current_object.game

            # Add sensor.
            ops_logic.sensor_add(type='ALWAYS')
                                 #name='Always')
                                 #object=cube_name)
            sensor = game_engine.sensors[-1]

            # Add controller.
            ops_logic.controller_add(type='LOGIC_AND')
                                     #name='And')
                                     #object=cube_name)
            controller = game_engine.controllers[-1]

            # Add actuator.
            ops_logic.actuator_add(type='ACTION')
                                   #name='Action',
                                   #object=cube_name)
            actuator = game_engine.actuators[-1]

            # Set actuator action to cube's animation data action.
            actuator.action = current_object.animation_data.action

            # Play mode options are:
            # ['PLAY', 'PINGPONG', 'FLIPPER', 'LOOPSTOP', 'LOOPEND', 'PROPERTY']
            # 'PLAY' is the default.
            #actuator.play_mode = play_mode

            # Set frame end to scene end.
            #actuator.frame_end = scene.frame_end
            actuator.frame_end = frames_to_be_played

            # Link logic together.
            sensor.link(controller)
            actuator.link(controller)


The above script puts the logic bricks to the objects that have an action and ignores the ones that don't have an action, which is good, but not what I'm after.

The ideal case would be to cancel the whole process if even one of the selected objects is missing an action. And notify about that with a message by using this method, which is this snippet code:

import bpy

class RENDER_OT_test(bpy.types.Operator):
    bl_idname = 'render.actionerrormessage'
    bl_label = 'actionErrorMessage'
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        self.report({'INFO'}, 'Cancelling... All the selected objects must have an action.')
        return {'FINISHED'}

bpy.utils.register_class(RENDER_OT_test) # test call to the newly defined operator bpy.ops.render.actionerrormessage() - try out by running the script and pressing spacebar and typing actionErrorMessage
My friend managed to achieve this with a bit nicer code than my artistic approach :)

GitHub link

Code:

import bpy

#########################################################
# INSERT ACTION LOGIC BRICKS TO SELECTED OBJECTS SCRIPT #
#########################################################

#########################################################
# Note:
#
# Each of the selected objects must have a transform 
# (Location/Rotation/Scale) action (animation/keyframes) 
# before running this script. The action can be empty.
# Otherwise nothing will be inserted to the objects.
#########################################################

############
# Settings #
############

action_brick_start_frame = 0

action_brick_end_frame = 9999 

# action_brick_end_frame = bpy.context.scene.frame_end
# Uncomment to set the Action Logic Brick end frame to be 
# the end frame of the Timeline.

#############################################################
# Make sure that each of the selected objects has an action #
# Credit goes mostly to Sakari Ekroth                       #
#############################################################

selection = bpy.context.selected_objects
noActionObjs = []
for obj in selection:
  if not obj.animation_data or not obj.animation_data.action:
    noActionObjs.append(obj.name)

if len(noActionObjs) &gt; 0:
  print ("Objects missing action: %s" % ", ".join(noActionObjs))
  def oops(self, context):
      self.layout.label("All of the selected objects must have an action. Cancelling... ")

  bpy.context.window_manager.popup_menu(oops, title="Error", icon='ERROR')
  print("All of the selected objects must have an action. Cancelling... ")

####################################################################
# The following adds the Logic Bricks to objects that allow them to 
# be playable in Blender Game Engine, but only to the selected 
# objects that have an action. Actionless objects are ignored.
# Credit goes mostly to Jeremy Behreandt
####################################################################

else:
  print("Inserting some Logic Bricks to the selected objects")
  ops = bpy.ops
  context = bpy.context

  # Cache shortcuts.
  ops_mesh = ops.mesh
  ops_object = ops.object
  ops_logic = ops.logic
  scene = context.scene

  for obj in selection:
    if obj.animation_data and obj.animation_data.action:

      bpy.context.scene.objects.active = obj
      current_object = context.active_object
      # Cache shortcut to cube's game engine.
      game_engine = current_object.game

      # Add sensor.
      ops_logic.sensor_add(type = "ALWAYS")
                            #name='Always')
                            #object=cube_name)
      sensor = game_engine.sensors[-1]

      # Add controller.
      ops_logic.controller_add(type = "LOGIC_AND")
                                #name='And')
                                #object=cube_name)
      controller = game_engine.controllers[-1]

      # Add actuator.
      ops_logic.actuator_add(type = "ACTION")
                              #name='Action',
                              #object=cube_name)
      actuator = game_engine.actuators[-1]

      # Set actuator action to cube's animation data action.
      actuator.action = current_object.animation_data.action

      # Play mode options are:
      # ['PLAY', 'PINGPONG', 'FLIPPER', 'LOOPSTOP', 'LOOPEND', 'PROPERTY']
      # 'PLAY' is the default.
      #actuator.play_mode = play_mode

      # Set frame start to scene end.
      actuator.frame_start = action_brick_start_frame

      # Set frame end to scene end.
      actuator.frame_end = action_brick_end_frame

      # Link logic together.
      sensor.link(controller)
      actuator.link(controller)