stafino
stafino

Reputation: 37

Fixing UnboundLocalError: local variable 'name' referenced before assignment in python

Reading a text file with names and birthdays in a function printBook(), returning name, birthday and referencing it later on in another function I get:

UnboundLocalError: local variable 'name' referenced before assignment

Code:

with open("scratch.txt") as file:

    def printBook():
        for line in file:
            name, month, date = line.split(",")
            print("Name:", name, "    Month:", month, "    Date:", date)
        return name, month, date

    def givenMonthPrintsElse(monthGiven):
        obj = printBook()
        if monthGiven == obj[1]:
            print("Name:", obj[0], "Day:", obj[2])

    printBook()
    givenMonthPrintsElse("Feb")

Upvotes: 0

Views: 1178

Answers (2)

MatBBastos
MatBBastos

Reputation: 401

Although there is already an accepted answer, I believe it does not deal with the real issue in the question. Elton's answer will prevent the exception from being thrown, but will not render the desired output, from what I understood of the question.

The Real Issue

The issue here is that when calling the printBook() function inside the givenMonthPrintsElse() function, there is nothing left to read in the file, therefore leading to no line objects, which skips the for loop, returning three unassigned variables (name, month and date).

This happens because the with ... open statement is misplaced. Once the file object is read on the printBook() function, the cursor is at EOF (end of file), thus nothing left to be read. Calling again another function that requires the output of printBook() under the same with ... open statement results in empty output. You can confirm this by commenting out the first call to printBook(), and you should get the desired output.

Solution (okay)

The simplest way I can think that solves it is moving the with ... open statement inside the printBook() function, like this:

def printBook():
    with open("scratch.txt") as file:
        for line in file:
            name, month, date = line.split(",")
            print("Name:", name, "    Month:", month, "    Date:", date)
        return name, month, date


def givenMonthPrintsElse(monthGiven):
    obj = printBook()
    if monthGiven == obj[1]:
        print("Name:", obj[0], "Day:", obj[2])


printBook()
givenMonthPrintsElse("Feb")

An important remark here is that, although it solves the issue, I suppose this is not the real intent of the OP, since it only allows to use the last line of the file (even though it reads through all of them). That is because name, month and date are overwritten at each iteration/line of the file, and only the last ones are returned by printBook().

Solution (better)

So, as following, a simple structure allows to access any line of the file:

def fileToList(fileName):
    with open(fileName) as file:
        values = file.readlines()
    return values


def printNameDate(fileList, monthGiven, entry=1):
    if monthGiven in fileList[entry-1]:
        name, month, date = fileList[entry-1].split(",")
        print("Name:", name, "\nDay:", date)


book = fileToList("scratch.txt")
printNameDate(book, "Feb")

This way, in the book object you have a list of the content of all the lines, as strings, that afterwards you can split and process as desired. The printNameDate() function uses a list of strings (as the one returned by fileToList() and a line number (named entry)) to get the desired output.

Upvotes: 1

Elton Viana
Elton Viana

Reputation: 301

You're declaring the name variable inside the for loop and accessing outside (in the return statement).

The easiest way to solve this is by declaring the variables before the for loop, so the printBook function would be something like:

def printBook():
    name, month, date = None, None, None
    for line in file:
        name, month, date = line.split(",")
        print("Name:", name, "    Month:", month, "    Date:", date)
    return name, month, date

PS: As @Chris pointed out, the problem isn't just because you're accessing the variables outside the loop (python accepts it), but because when the loop doesn't run, your variables aren't declared.

Upvotes: 0

Related Questions