There are many ways to attach an object to a bone. The simplest is bone parenting. The script below should do it.
import bpy
# Get the armature object using its object name.
arm = bpy.data.objects['Rig']
# Get the active bone. I assume the weapon needs to be attached to this bone. If the name of the bone is known, this step can be skipped.
bone = arm.data.bones.active
# Get the active object. I assume the active object is the weapon.
obj = bpy.context.active_object
# Modify the parenting parameters to achieve bone parenting.
obj.parent = arm # Armature object
obj.parent_bone = bone.name # Bone name
obj.parent_type = 'BONE'
This will place the weapon at the tip of the bone and orient it to match the bone orientation. If this is not the desired position and orientation, you will have to modify the weapon transforms.
If you already prepared a setup where the weapon just needs to be parented to a proxy object (for example, an Empty), you can use object parenting which is simpler as shown below.
import bpy
empty = bpy.data.objects['Empty']
obj = bpy.context.active_object
obj.parent = empty
Edit: I would like to point out a few issues with the revised code in the question. I leave them as comments below.
# I assume you have "import bpy" somewhere before this snippet and you
# assigned the variables: bone_name, armature_obj, meshobj.
# 1. There is no need to switch to edit mode. We're dealing with object
# relations which is done on the object level.
# 2. This is an operator, which means it depends on the context. You
# need to make sure that the object of interest is active before
# running this.
bpy.ops.object.mode_set(mode='EDIT')
# Looking below, it doesn't seem you're using the bone at all. You're
# also not depending on the bone to be selected nor active. Also, bones
# are not objects. Bones to an armature object are like vertices to a
# mesh object.
bone_obj = armature_obj.data.bones[bone_name]
bone_obj.select = True
armature_obj.data.bones.active = bone_obj
# Since the switch to object mode was unnecessary, the switch back to
# object mode is unnecessary too.
bpy.ops.object.mode_set(mode='OBJECT')
# Making the object active and selecting it are both only needed if
# you're running an operator that requires the context to make sense.
bpy.context.view_layer.objects.active = meshobj
meshobj.select_set(True)
# If you already have a handle on the meshobj and the armature_obj, and
# know the bone_name, these three lines are all you need.
meshobj.parent = armature_obj
meshobj.parent_bone = bone_name
meshobj.parent_type = 'BONE'
Edit: This is how the script would change if one wants to parent the mesh_obj
to an empty_obj
and parent the empty_obj
to a bone named bone_name
under armature_obj
?
# I assume bpy was imported and the variables were already assigned. Something like the following lines will do:
import bpy
mesh_obj = bpy.data.objects["Cube"]
armature_obj = bpy.data.objects["Armature"]
empty_obj = bpy.data.objects["Empty"]
bone_name = "Bone"
# This is where the actual parenting happens.
mesh_obj.parent = empty_obj
empty_obj.parent = armature_obj
empty_obj.parent_bone = bone_name
empty_obj.parent_type = 'BONE'