1

This code runs without errors. But in the function find_available_filenumber the variable render_folder isn't declared. So my question is why this doesn't produce an error?

If I remove full_filename as a parameter, I get the error:

UnboundLocalError: local variable 'full_filename' referenced before assignment.

I don't understand why this doesn't also happen with render_folder, in my code example below:

import bpy
import os

#Functions
def find_available_filenumber(full_filename):
    file_number = 1

    while os.path.exists(render_folder + "\\" + full_filename):
        file_number += 1
        full_filename = create_full_filename(filename, file_number)

    return file_number

def create_full_filename(filename, file_number):
    file_extension = ".avi"
    full_filename = filename + "_" + str(file_number) + file_extension    

    return full_filename

#Paths and names
project_folder = "F:\\06_MotionPath_Dev\\"
os.chdir(project_folder)

render_folder = "Render\\QuickRenderAddon"
filename = bpy.context.scene.name  #Returns "QuickRenderAddon"
full_filename = create_full_filename(filename, 1)
filepath = render_folder + "\\" + full_filename

available_number = find_available_filenumber(full_filename)
print("Avail nmb: " + str(available_number))
Taku
  • 31,927
  • 11
  • 74
  • 85
Einar
  • 1,001
  • 3
  • 11
  • 28

3 Answers3

3

Ah yes the classic "Referenced before Assignment"

I wrote some example code to show what is going on.

test = "toast!"
toast = "test!"

def func():
    print test
    print toast

func()

The output of the above is

toast!
test!

This shows that we can read global variables, but what about writing to them? I don't want 'toast' to be 'test!' anymore, but rather 'bread+toaster!'. Let's write this out.

test = "toast!"
toast = "test!"

def func():
    print test
    toast = "bread+toaster!"
    print toast

func()
print toast

This outputs

toast!
bread+toaster!
test!

You'll notice that we were able to print the locally assigned variable, but the global variable did not change. Now, let's look at another example.

test = "toast!"
toast = "test!"

def func():
    print test
    print toast
    toast = "bread+toaster!"
    print toast

func()
print toast

This will throw the error

UnboundLocalError: local variable 'toast' referenced before assignment

Why? Because you're later declaring your variable 'toast' as a local variable. Python notices this and stops the code to prevent errors. You setting 'toast' later is not changing the global variable, but rather declaring a local one within the function called 'toast'.

How can you fix this?

The first would be to add a global clause inside your function

test = "toast!"
toast = "test!"

def func():
    global toast
    print test
    print toast
    toast = "bread+toaster!"
    print toast

func()
print toast

This outputs

toast!
test!
bread+toaster!
bread+toaster!

You can also modify your code into a class structure, as such.

class bread():
    def __init__(self):
        self.test = "toast!"
        self.toast = "test!"

    def func(self):
        print self.test
        print self.toast
        self.toast = "bread+toaster!"
        print self.toast

b = bread()
b.func()

In my opinion, classes are the best solution as it will increase modularity and help you reduce spaghetti code.

ollien
  • 4,418
  • 9
  • 35
  • 58
1

Edit: Ignore me, I'm on mobile, so I didn't properly read.

The error states "referenced before assignment". In other words, you are trying to read a value from that variable before you have written a value to it.

I have a feeling this error is being cause in your while conditional, as you are checking the value before writing to it in the body of the while loop.

DiJuMx
  • 524
  • 5
  • 10
1

This code runs without errors. But in the function find_available_filenumber the variable render_folder isn't declared. So my question is why this doesn't produce an error?

This is because render_folder is declared at the time find_available_filenumber is called, even though its not declared when your function is defined.

pad
  • 2,296
  • 2
  • 16
  • 23