Reputation: 37
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
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 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.
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()
.
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
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