How to automatically fit the camera to objects in the view?
There is an operator to do exactly this. it can be called from Python or accessed from a menu.


Select the objects you wish to put in the camera view.
View -> Align View -> Align Active Camera to Selected.


Or run the operator: bpy.ops.view3d.camera_to_view_selected()

eg:

import bpy
from bpy import context

# Select objects that will be rendered
for obj in scene.objects:
    obj.select = False
for obj in context.visible_objects:
    if not (obj.hide or obj.hide_render):
        obj.select = True

bpy.ops.view3d.camera_to_view_selected()


There is also an object method to place a camera given input coordinates: Object.camera_fit_coords()



If you want a margin around the objects, you could temporarily reduce the cameras view angle, then restore it afterwards, or simply move the camera back along its Z axis.