Looking for an export script object position, rotation & custom properties

Hey there all,
Does anyone know of a script that will export all selected object positions & rotations along with object custom properties “Property Name” & “Property Value” to a .txt file.
If not could anyone offer any advice on how i could write a script to do so?

Would like the .txt file to be something like:

[start]
Object: Mesh1
X#,Y#,Z#
RX#,RY#,RZ#
Property Name, Property Value
Property Name, Property Value
Property Name, Property Value
Property Name, Property Value

Object: Mesh2
X#,Y#,Z#
RX#,RY#,RZ#
Property Name, Property Value
Property Name, Property Value

Object: Mesh3
X#,Y#,Z#
RX#,RY#,RZ#
Property Name, Property Value
Property Name, Property Value
Property Name, Property Value
[end]

Any help would be greatly appreciated.

dunno bout custom properties but the rest seems pretty simple… use something like the following and write to a file


print('[start]')
for a in bpy.context.selected_objects:
	print('Object:'+a.name)
	print(str(a.location[0])+','+str(a.location[1])+','+str(a.location[2]))
	print(str(a.rotation_euler[0])+','+str(a.rotation_euler[1])+','+str(a.rotation_euler[2]))
	print('')
print('[end]')

Thanks doublebishop.
I have no idea how to even implement this.
I have tried a couple of tutorials on writing export scripts but keep getting errors in them even when copying & pasting the code from the tutorials into a file.
Here is one script if someone could help with where i should place the above code or even help out with fixing the code i have would be great.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bl_info = {
“name”: “My Data Format”,
“author”: “Bruce Sutherland”,
“blender”: (2,6,2),
“version”: (0,0,1),
“location”: “File > Import-Export”,
“description”: “Export custom data format”,
“category”: “Import-Export”
}

import bpy
from bpy_extras.io_utils import ExportHelper

class ExportMyFormat(bpy.types.Operator, ExportHelper):
bl_idname = “export_my_format.fmt”;
bl_label = “My Data Exporter”;
bl_options = {‘PRESET’};

filename_ext    = ".txt";

def execute(self, context):
    return {'Finished'};

def menu_func(self, context):
self.layout.operator(ExportMyFormat.bl_idname, text=“My Model Format(.txt)”);

def register():
bpy.utils.register_module(name);
bpy.types.INFO_MT_file_export.append(menu_func);

def unregister():
bpy.utils.unregister_module(name);
bpy.types.INFO_MT_file_export.remove(menu_func);

if name == “main”:
register()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I have very little to no coding experience with blender & am planing on using blender as a level editor for use with blitz3d

Ok so i now have this but keep getting TabError: Inconsistent uses of tabs & spaces in indentation.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bl_info = {
“name”: “My Data Format”,
“author”: “Bruce Sutherland”,
“blender”: (2,6,2),
“version”: (0,0,1),
“location”: “File > Import-Export”,
“description”: “Export custom data format”,
“category”: “Import-Export”
}

import bpy
from bpy_extras.io_utils import ExportHelper

class ExportMyFormat(bpy.types.Operator, ExportHelper):
bl_idname = “export_my_format.fmt”;
bl_label = “My Data Exporter”;
bl_options = {‘PRESET’};
filename_ext = “.fmt”;

def execute(self, context):
  
    print('[start]')
    for a in bpy.context.selected_objects:
    print('Object:'+a.name)
    print(str(a.location[0])+','+str(a.location[1])+','+str(a.location[2]))
    print(str(a.rotation_euler[0])+','+str(a.rotation_euler[1])+','+str(a.rotation_euler[2]))
    print('')
    print('[end]')
    
    return {'Finished'};

def menu_func(self, context):
self.layout.operator(ExportMyFormat.bl_idname, text=“My Model Format(.fmt)”);

def register():
bpy.utils.register_module(name);
bpy.types.INFO_MT_file_export.append(menu_func);

def unregister():
bpy.utils.unregister_module(name);
bpy.types.INFO_MT_file_export.remove(menu_func);

if name == “main”:
register()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

tabs are important within python
notice how my loop has a indentation? it signifys that the loop happens at that level, as soon as that indentation level is broken, then the loop ends.

also your script must either use spaces or tabs to indent… and it must be consistant over your whole script.

Thanks again doublebishop but still not having much luck, keep getting an error when i run the script.
When i copy and paste the code here it aligns everything to the left of the page. I will attach the .py file.
Very much appreciating the help.
Couldn’t attach the file but here it is http://www.mediafire.com/view/c80sw3t7qyipu7f/BlenderExportScriptTut1.py

@doublebishop: you can simplify that code to:

print('[start]')
for ob in bpy.context.selected_objects:
    print("Object:", ob.name)
    print("%f,%f,%f" % ob.location[:])
    print("%f,%f,%f" % ob.rotation_euler[:])
    print('')
print('[end]')

Thanks CoDEmanX… i am still learning python :wink:

the first problem lies between lines 21 and 31… the def execute, you are defining a function but not having anything in that function, from lines 23 to 31 should be indented a second time.

next problem is on line 31… return finished… finished needs to be all caps

then… the code i provided only prints it out… it doesnt actually save it anywhre… you should have a look at a python file like this one to see how they set up / write out information http://projects.blender.org/tracker/download.php/153/467/25653/20425/io_vue_camera.py

Thanks again doublebishop, i will have a look & see how it all goes. :slight_smile:

Ok, struggling with this big time.
Please bear with me. I don’t really understand python script but i am tipping the principles are the same as what i am used to using with Blitz3D.
So the with the For loop that prints out the object info, do i then have to store that info in a variable eg: Objects = (‘Object:’+a.name) and then write Objects to a line within a file within the for loop and for each line of code within that loop?

Ok after finding another tutorial i got the script working the way i want it to.

Nice work mate!

Thanks doublebishop & thanks for the help.
Now to try and figure out how to access the custom properties info, i can see that blender will display the properties when changed but trying to access them through the console is proving tricky.
This is what comes up when i change values:
bpy.data.window_managers[“WinMan”].(null) = “Health#”
bpy.data.window_managers[“WinMan”].(null) = “100”
bpy.ops.wm.properties_edit(data_path=“object”, property=“Health#”, value=“100”, min=0, max=1, description="")

Is it possible to create your own custom property panel & access the info via scripting?

Ignore the operator log and do it properly:

wm = bpy.context.window_manager
wm["Health#"] = 100

Or use a custom panel for custom bpy.props properties:

import bpy


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        ob = context.object
        props = ob.my_props
        layout.prop(props, "my_str")
        layout.prop(props, "my_int")
        layout.prop(props, "my_float")


class MyProps(bpy.types.PropertyGroup):
    my_str = bpy.props.StringProperty()
    my_int = bpy.props.IntProperty()
    my_float = bpy.props.FloatProperty()


def register():
    bpy.utils.register_module(__name__)
    bpy.types.Object.my_props = bpy.props.PointerProperty(type=MyProps)


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Object.my_props


if __name__ == "__main__":
    register()


Thanks CoDEmanX
I found a piece of code that was very close to what i am after & made a few changes to it to suit what i need.

The one last thing i would like to be able to do is have the Field: & Value: input boxes as a listbox that will store a text input so that i can use it on other objects instead of having to retype the text every time. Is it possible? & could anyone point me in the right direction to an example.

Slowly getting there. :slight_smile:


bl_info = {
    "name":         "OwlEngine Properties",
    "author":       "Peter Cimo",
    "blender":      (2,6,2),
    "version":      (0,0,1),
    "location":     "File > Import-Export",
    "description":  "Adds properties and panel to Object",
    "category":     "Object"
}
import bpy


# Owl Engine Properties
# Created by Peter Cimo @ 2014


# ----------------------------------
class EventSettings(bpy.types.PropertyGroup):
    event_field = bpy.props.StringProperty()#EnumProperty(items=event_field_items, default="on_activate" , options={'HIDDEN', 'ANIMATABLE'});
    event_value = bpy.props.StringProperty()


class EventSettingsAddOp(bpy.types.Operator):
    bl_label = "Add event"
    bl_idname = "collection.event_add"
    
    def invoke(self, context, event):
        obj = context.object
        collection = obj.event_settings
        collection.add()
        return {'FINISHED'}


class EventSettingsRemoveOp(bpy.types.Operator):
    bl_label = "Remove event"
    bl_idname = "collection.event_remove"
    
    def invoke(self, context, event):
        obj = context.object
        collection = obj.event_settings
        index = obj.event_settings_index
        collection.remove(index)
        return {'FINISHED'}


class EventSettingsItem(bpy.types.UIList):
        def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
                layout.prop(item, "event_field", "Field");
                layout.prop(item, "event_value", "Value");


# ----------------------------


class MyObjectProperties(bpy.types.Panel):     
    bl_label = "My Custom Properties"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
 
    def draw(self, context):
        obj = bpy.context.active_object;
        #self.layout.prop(obj, "auto_activate", "Auto Activate");
        #self.layout.label(text="Animation", icon='ANIM')
        #anim_layout = self.layout.box();
        #anim_layout.prop(obj, "anim_fps", "FPS");
        #anim_layout.prop(obj, "anim_loop", "Loop");
        
        #self.layout.label(text="Events", icon='WORLD')
        activation_layout = self.layout.box();
        row = activation_layout.row()
        row.template_list(listtype_name="EventSettingsItem", dataptr=obj, propname="event_settings", active_dataptr=obj, active_propname="event_settings_index")
        col = row.column(align=True)
        col.operator("collection.event_add", icon="ZOOMIN", text="")
        col.operator("collection.event_remove", icon="ZOOMOUT", text="")
        
        
        
        


def register():
    bpy.utils.register_class(EventSettings)
    bpy.utils.register_class(EventSettingsAddOp)
    bpy.utils.register_class(EventSettingsRemoveOp)
    bpy.utils.register_class(EventSettingsItem)
    bpy.utils.register_class(MyObjectProperties)
    
    # events
    bpy.types.Object.event_settings_index = bpy.props.IntProperty(min= 0,default= 0)
    bpy.types.Object.event_settings = bpy.props.CollectionProperty(type=EventSettings)
    
    
def unregister():
    bpy.utils.unregister_class(EventSettings)
    bpy.utils.unregister_class(EventSettingsAddOp)
    bpy.utils.unregister_class(EventSettingsRemoveOp)
    bpy.utils.unregister_class(EventSettingsItem)
    bpy.utils.unregister_class(MyObjectProperties)  
     
if __name__ == "__main__":
    register()

Sounds like you don’t actually want to store it on the object level? You can use bpy.types.Scene, although it’s per scene, but there’s in fact no type that has a single instance AND saves to .blend.

btw, the version number tuple is wrong:

"blender":      (2,6,2),

it needs to be

"blender":      (2,62,0),

I’m not 100% sure what you mean by storing it per scene, all i need to do is be able to access the custom properties for each object & write them out to a file. I have found how to access the custom properties in the new panel i have created but what i would like to do is where i input the text into “field: & value:” input boxes on the created panel is to have it as a text/list box so i don’t have to keep typing out the same thing multiple times.

I will be exporting the info to a .txt file for use in another program & for example i may have multiple objects i will be using as a health or ammo pickup.
Ammo% = 10
Ammo% = 20
Ammo% = 100

Health% = 10
Health% = 20
Health% = 50
Health% = 100

So instead of having to type Health, Ammo, 10, 20,100 for each object, if i could just select it from a list it would make things a lot easier but i still need the ability to add text to the selection, for instance i would still have to type the value of 50 for one of the Health% fields.

Cheers for the info on the tuple. :slight_smile:

Ok been doing more work on the export code and will get back to the panel at a later time as it’s not overly important.
I have been following through the same tutorial as i did for writing out the object name, location & rotation & am kind of stuck on a part to export my custom properties. I can access the properties & write them to a .txt file but it’s not coming out in the format i would like.
Here is the code (part original and the part added), i know it has to do with the two for loops but i am not to sure why it’s doing it in the way it is.


def execute(self, context):


        file = open(self.filepath,'w')
        file.write('[start]')
        file.write("
")
        for a in bpy.context.selected_objects:
            file.write('Object:'+a.name)
            file.write("
")
            file.write('X#:'+str(a.location[0]))
            file.write("
")
            file.write('Y#:'+str(a.location[2]))
            file.write("
")
            file.write('Z#:'+str(a.location[1]))
            file.write("
")
            file.write('Xrot#:'+str(a.rotation_euler[0]))
            file.write("
")
            file.write('Yrot#:'+str(a.rotation_euler[2]))
            file.write("
")
            file.write('Zrot#:'+str(a.rotation_euler[0]))
            file.write("
")
            
            objname = a.name
            objfields = bpy.data.objects[objname].event_settings
            objvalues = bpy.data.objects[objname].event_settings
            
            fields = []
            values = []
            
           
            for i in objfields:
                for z in objvalues:
                    fields.append(i.event_field)
                    values.append(z.event_value)
                    file.write(str(fields)+"=")
                    file.write(str(values)+"
")
                
                
            #;;;;;;;;;;;;loop needed to perform same as below
            #file.write(str(bpy.data.objects[objname].event_settings[0].event_field +"="))
            #file.write(str(bpy.data.objects[objname].event_settings[0].event_value))
            #file.write("
")
            #file.write(str(bpy.data.objects[objname].event_settings[1].event_field +"="))
            #file.write(str(bpy.data.objects[objname].event_settings[1].event_value))
            #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                
            file.write("

")
            
        file.write('[end]')
    
        
        return {'FINISHED'};

This is what it writes out & is the closest i have come to getting it how i need it.


[start]
Object:Cube
X#:0.0
Y#:0.0
Z#:0.0
Xrot#:0.0
Yrot#:0.0
Zrot#:0.0
['health']=['100']
['health', 'health']=['100', '25']
['health', 'health', 'health']=['100', '25', '75']
['health', 'health', 'health', 'armour']=['100', '25', '75', '100']
['health', 'health', 'health', 'armour', 'armour']=['100', '25', '75', '100', '25']
['health', 'health', 'health', 'armour', 'armour', 'armour']=['100', '25', '75', '100', '25', '75']
['health', 'health', 'health', 'armour', 'armour', 'armour', 'ammo']=['100', '25', '75', '100', '25', '75', '100']
['health', 'health', 'health', 'armour', 'armour', 'armour', 'ammo', 'ammo']=['100', '25', '75', '100', '25', '75', '100', '25']
['health', 'health', 'health', 'armour', 'armour', 'armour', 'ammo', 'ammo', 'ammo']=['100', '25', '75', '100', '25', '75', '100', '25', '75']

[end]

What i need is & to get rid of the [ ] around both the strings & values


health = 100
armour = 25
ammo = 75

Any help would be greatly appreciated.

Sounds to me like you want a CollectionProperty plus presets?

Here’s a complex example:

import bpy
from bpy.props import *

sire_items = (
    ('s', "Scale", ""),
    ('i', "Inset", ""),
    ('r', "Rotate", ""),
    ('e', "Extrude", "")
)

sire_items_dict = {}
for identifier, label, description in sire_items:
    sire_items_dict[identifier] = label

sire_step_presets_dict = {
    'BASIC_1': ("Basic 1", "Base preset",
        (
            {
                'name': 'Scale',
                'val': 1.67,
            },
            {
                'name': 'Rotate',
                'val': -0.5,
                'rot': 'ccw',
            }
        )
    ),
    'BASIC_2': ("Basic 2", "Another preset",
        (
            {
                'name': 'Inset',
                'val': 22.2,
                'other': 'out',
            },
            {
                'name': 'Rotate',
                'val': 4.4,
            }
        )
    )
}

sire_step_presets = [(identifier, label, description) for identifier, (label, description, settings) in sire_step_presets_dict.items()]


class SireStep(bpy.types.PropertyGroup):
    name = StringProperty()
    
    trans = EnumProperty(items=sire_items) # default 's' required?
    
    val = FloatProperty(min=0.001, soft_max=1000, default=1.0, precision=3)
    
    rot = EnumProperty(items=(
        ('cw', 'CW', ''),
        ('ccw', 'CCW', '')),
        name="Rotation" # name required if enum expanded, or labels will be missing
    )
    
    other = EnumProperty(items=(
        ('in', 'In', ''),
        ('out', 'Out', '')),
        name="Other"
    )
    
class Sire(bpy.types.PropertyGroup):
    type_add = EnumProperty(
        items=sire_items,
        name = "some name",
        default = 's'
    )
    
    steps = CollectionProperty(type=SireStep, name="Sire Step")
    index = IntProperty() # min/max/default?


class SIRE_UL_steplist(bpy.types.UIList):
    
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        
        # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
        if self.layout_type in {'DEFAULT', 'COMPACT'}:

            row = layout.row(align=True)
            row.label(item.name)
            
            row.prop(item, "val", text="")
            
            sub = row.row(align=True)
            sub.scale_x = 0.4
            
            if item.name == sire_items_dict['r']:
                sub.prop(item, "rot", expand=True)
            else:
                sub.prop(item, "other", expand=True) # if not expanded, use text=""
            
        # 'GRID' layout type should be as compact as possible (typically a single icon!).
        elif self.layout_type in {'GRID'}:
            layout.alignment = 'CENTER'
            layout.label("", icon_value=icon)


# ------ operator 0 ------ add item to collection
class VIEW3D_OT_sire_step_add(bpy.types.Operator):
    bl_idname = 'view3d.sire_step_add'
    bl_label = 'Add'
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return (context.active_object and 
                context.active_object.type == 'MESH' and 
                context.mode == 'EDIT_MESH')

    def execute(self, context):
        steps = context.scene.sire.steps

        step = steps.add()
        step.name = sire_items_dict[context.scene.sire.type_add]
        
        context.scene.sire.index = len(steps) - 1
        
        return {'FINISHED'}


# ------ operator 1 ------ remove item from collection
class VIEW3D_OT_sire_step_remove(bpy.types.Operator):
    bl_idname = 'view3d.sire_step_remove'
    bl_label = 'Remove'
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return (context.active_object and
                context.active_object.type == 'MESH' and 
                context.mode == 'EDIT_MESH' and
                len(context.scene.sire.steps) > 0)
        
    def execute(self, context):
        idx = context.scene.sire.index
        move_idx = len(context.scene.sire.steps) - 1 == idx
        context.scene.sire.steps.remove(idx)
        if move_idx:
            context.scene.sire.index -= 1
        
        return {'FINISHED'}
    
    
# ------ operator 2 ------ move item up
class VIEW3D_OT_sire_step_moveup(bpy.types.Operator):
    bl_idname = 'view3d.sire_step_moveup'
    bl_label = 'Move up'
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return (context.active_object and
                context.active_object.type == 'MESH' and
                context.mode == 'EDIT_MESH' and
                len(context.scene.sire.steps) > 0 and
                context.scene.sire.index > 0)

    def draw(self, context):
        layout = self.layout
        
    def execute(self, context):
        idx = context.scene.sire.index
        context.scene.sire.steps.move(idx, idx-1)
        context.scene.sire.index -= 1

        return {'FINISHED'}


# ------ operator 3 ------ move item down
class VIEW3D_OT_sire_step_movedown(bpy.types.Operator):
    bl_idname = 'view3d.sire_step_movedown'
    bl_label = 'Move down'
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return (context.active_object and 
                context.active_object.type == 'MESH' and
                context.mode == 'EDIT_MESH' and
                len(context.scene.sire.steps) > 0 and
                context.scene.sire.index < len(context.scene.sire.steps) - 1)

    def execute(self, context):
        idx = context.scene.sire.index
        context.scene.sire.steps.move(idx, idx+1)
        context.scene.sire.index += 1
        
        return {'FINISHED'}
    
    
class VIEW3D_OT_sire_step_clear(bpy.types.Operator):
    bl_idname = 'view3d.sire_step_clear'
    bl_label = 'Clear all'
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    def execute(self, context):
        context.scene.sire.steps.clear()
        return {'FINISHED'}


class VIEW3D_OT_sire_step_preset(bpy.types.Operator):
    bl_idname = 'view3d.sire_step_preset'
    bl_label = 'Add Preset Steps'
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    preset = bpy.props.EnumProperty(items=sire_step_presets)

    def execute(self, context):
        steps = context.scene.sire.steps
        label, description, settings = sire_step_presets_dict[self.preset]
        for elem in settings:
            item = steps.add()
            for k, v in elem.items():
                setattr(item, k, v)
        context.scene.sire.index = len(steps) - 1
        return {'FINISHED'}


class VIEW3D_MT_sire_specials(bpy.types.Menu):
    bl_label = "Specials"
    bl_idname = "VIEW3D_MT_sire_specials"
    
    def draw(self, context):
        layout = self.layout
        
        layout.operator("view3d.sire_step_clear", icon="X")
        layout.separator()
        layout.operator_enum("view3d.sire_step_preset", "preset")
        

class VIEW3D_PT_sire_steplist(bpy.types.Panel):
    """Tooltip"""
    bl_label = "SIRE"
    bl_idname = "VIEW3D_PT_sire_steplist"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_context = "mesh_edit"

    def draw(self, context):
        layout = self.layout

        layout.prop(context.scene.sire, "type_add", expand=True)

        row = layout.row()
        row.template_list("SIRE_UL_steplist", "", context.scene.sire, "steps", context.scene.sire, "index", rows=4, maxrows=10)
        
        col = row.column(align=True)
        col.operator("view3d.sire_step_add", text="", icon="ZOOMIN")
        col.operator("view3d.sire_step_remove", text="", icon="ZOOMOUT")
        col.menu("VIEW3D_MT_sire_specials", text="", icon="DOWNARROW_HLT")
        
        col.separator()
        col.operator('view3d.sire_step_moveup', text='', icon='TRIA_UP')
        col.operator('view3d.sire_step_movedown', text='', icon='TRIA_DOWN')
            

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.sire = PointerProperty(type=Sire)

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.sire


if __name__ == "__main__":
    register()

Shows up in T toolshelf if a mesh object is selected and in editmode. Use the specials menu to add from presets (dark arrow down).

If you have two lists:
list_1 = [‘health’, ‘health’, ‘health’]
list_2 = [‘100’, ‘25’, ‘75’]

Then use zip():

for l1, l2 in zip(list_1, list_2):
    print("%s = %s" % (l1, l2))