1
$\begingroup$

I'm trying to create a csv file to include the number and the filenames created using Python.

Example: The text in the output.csv file would look like this.

1,Filename_01.jpg,001
2,Filename_02.jpg,002
3,Filename_03.jpg,003

The code I'm having problems with is:

#place filenames in array and export to csv file
csvLines = [ ";".join([ str(jpg_path) ]) + "\n"]
            
f = open( csv_outputfile, 'w' )
f.writelines( csvLines )
f.close()
            

Currently the output.csv file just includes one filename and no numbers (it keeps writing over things)

The full script is below:

import bpy
import os
from math import radians

Rangelow = 0
Rangehigh = 3.0
Delta = 1.5

#csv file with data
csv_outputfile = "/tmp/0/jpg/output.csv"

def decimal_range(start, stop, increment):
    while start < stop: # and not math.isclose(start, stop): Py>3.5
        yield start
        start += increment

# get the current path and make a new folder for the exported meshes
destination_path = '/tmp/0/jpg'

# if path doesn't exist, create, else skip that step
if not os.path.exists(destination_path):
    os.makedirs(destination_path)

# gather names
names = [o.name for o in bpy.context.selected_objects]

# deselect all
bpy.ops.object.select_all(action='DESELECT')

# iterate over named objects
for name in names:

     # select the object
    obj = bpy.data.objects[name]
    bpy.context.view_layer.objects.active = obj
    obj.select_set(True)
    
    
    for x in decimal_range(Rangelow, Rangehigh, Delta):
        for y in decimal_range(Rangelow, Rangehigh, Delta):
            for z in decimal_range(Rangelow, Rangehigh, Delta):
                #change GN value
                so = bpy.context.active_object
                #so.modifiers["working clip only gn"].modifiers["GeometryNodes"]["Input_7"] = 5
                #adj_gap = 5.0
                so.modifiers["GeometryNodes"]["Input_3"] = float(x)
                so.modifiers["GeometryNodes"]["Input_7"] = float(y)
                so.modifiers["GeometryNodes"]["Input_9"] = float(z)
                
                
                obj.update_tag() #https://developer.blender.org/T87006
                
                # export object with its name as file name
                #txt_adj_gap = str(obj.dimensions.x)
                txt_len_x = '_x_' + str(x) +'mm'
                txt_center_gap_y = '_y_' + str(y) +'mm'
                txt_hgt_z = '_z_' + str(z) +'mm'
                #print(type(txt_ar)
                
                
                jpg_path = os.path.join(destination_path, name + txt_len_x + txt_center_gap_y + txt_hgt_z +'.jpg')
                so.modifiers["GeometryNodes"]["Input_12"] = jpg_path #update filename in image
                
                #output to jpg file
                scene = bpy.context.scene
                scene.render.image_settings.file_format='JPEG'
                scene.render.filepath=jpg_path
                bpy.ops.render.render(write_still=1)
                


                #place filenames in array and export to csv file
                csvLines = [ ";".join([ str(jpg_path) ]) + "\n"]
                
                f = open( csv_outputfile, 'w' )
                f.writelines( csvLines )
                f.close()
                
$\endgroup$
4
  • 1
    $\begingroup$ seems like you are populating csvLines with a single filename and writing to the file in write mode which overwrites the file so you end up with a single filename in the csv file at the end. You can EITHER open the file in append mode using 'a' instead of 'w' OR use csvLines = csvLines + ..... to populate all the filenames in the csvLines variable and move the file writing code out of the for loop. Leaving the file writing code within the for loop will also get you the same result but highly inefficient $\endgroup$ Commented Jan 11, 2023 at 21:59
  • $\begingroup$ @FarhanAhmed Thanks what is csvLines = csvLines + .... seems like something is missing? $\endgroup$
    – Rick T
    Commented Jan 11, 2023 at 22:13
  • $\begingroup$ Also it is advised to use with when dealing with text files, otherwise if something goes wrong before your scripts gets a chance to close it, it never gets closed which can cause some funky behavior / memory leaks $\endgroup$
    – Gorgious
    Commented Jan 12, 2023 at 7:49
  • $\begingroup$ @RickT I meant change csvLines = [ ";".join([ str(jpg_path) ]) + "\n"] to csvLines = csvLines + [ ";".join([ str(jpg_path) ]) + "\n"] $\endgroup$ Commented Jan 12, 2023 at 17:02

1 Answer 1

3
$\begingroup$

You have to take the f = open( csv_outputfile, 'w' ) part out of the for loops. And include another variable that continuously appends the new lines in the loop. In this case I added csvLines and line_number. Here's your working script:

import bpy
import os
from math import radians

Rangelow = 0
Rangehigh = 3.0
Delta = 1.5

#csv file with data
csv_outputfile = "/tmp/0/jpg/output.csv"
csvLines = ""
line_number = 0

def decimal_range(start, stop, increment):
    while start < stop: # and not math.isclose(start, stop): Py>3.5
        yield start
        start += increment

# get the current path and make a new folder for the exported meshes
destination_path = '/tmp/0/jpg'

# if path doesn't exist, create, else skip that step
if not os.path.exists(destination_path):
    os.makedirs(destination_path)

# gather names
names = [o.name for o in bpy.context.selected_objects]

# deselect all
bpy.ops.object.select_all(action='DESELECT')


# iterate over named objects
for name in names:

     # select the object
    obj = bpy.data.objects[name]
    bpy.context.view_layer.objects.active = obj
    obj.select_set(True)
    
    
    for x in decimal_range(Rangelow, Rangehigh, Delta):
        for y in decimal_range(Rangelow, Rangehigh, Delta):
            for z in decimal_range(Rangelow, Rangehigh, Delta):
                #change GN value
                so = bpy.context.active_object
                #so.modifiers["working clip only gn"].modifiers["GeometryNodes"]["Input_7"] = 5
                #adj_gap = 5.0
                so.modifiers["GeometryNodes"]["Input_3"] = float(x)
                so.modifiers["GeometryNodes"]["Input_7"] = float(y)
                so.modifiers["GeometryNodes"]["Input_9"] = float(z)
                
                
                obj.update_tag() #https://developer.blender.org/T87006
                
                # export object with its name as file name
                #txt_adj_gap = str(obj.dimensions.x)
                txt_len_x = '_x_' + str(x) +'mm'
                txt_center_gap_y = '_y_' + str(y) +'mm'
                txt_hgt_z = '_z_' + str(z) +'mm'
                #print(type(txt_ar)
                
                
                jpg_path = os.path.join(destination_path, name + txt_len_x + txt_center_gap_y + txt_hgt_z +'.jpg')
                so.modifiers["GeometryNodes"]["Input_12"] = jpg_path #update filename in image
                
                #output to jpg file
                scene = bpy.context.scene
                scene.render.image_settings.file_format='JPEG'
                scene.render.filepath=jpg_path
                bpy.ops.render.render(write_still=1)
                
                #place filenames in array and export to csv file
                #csvLines = [ ";".join([ str(jpg_path) ]) + "\n"]
                line_number += 1
                csvLines += str(line_number) + "," + ";".join([ str(jpg_path) ]) + ",{:03d}".format(line_number) + "\n"

f = open( csv_outputfile, 'w' )
f.writelines( csvLines )
f.close()
$\endgroup$
1
  • 1
    $\begingroup$ Thanks! this worked all I had to add was line_number = 0 $\endgroup$
    – Rick T
    Commented Jan 12, 2023 at 6:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .