UnboundLocalError: local variable 'txt' referenced before assignment - python

Here is my program thus far. When I run it, I receive the error: "UnboundLocalError: local variable 'txt' referenced before assignment". I tried adding global before txt to declare it as a global variable, but I get another error when I do that. Any ideas what I am doing wrong? Thanks in advance.
def getwords():
#function to get words in the input file
try:
global txt
txt=open("sample.txt",'r')
except IOError:
print('Unable to open file')
words=[]
#read the file line by line
for line in txt:
#convert each line into words with space as delimiter
words=words+line.split()
return words
def wordcount(wordlist):
#function to count words in the file
#worddic is dictionary to store words frequency
worddic=dict()
for x in wordlist:
#convert word to lowercase to ignorecase
t=x.lower()
if(t not in worddic):
worddic[t]=0
worddic[t]=worddic[t]+1
max=-1
t=''
for x in worddic:
if(worddic[x]>max):
max=worddic[x]
t=x
return t
def letters(wordlist,lettercount):
#function to count letters in the file
for x in wordlist:
#For each word in the list
t=x.lower()
for y in t:
#for each letter in the word
if(not (y in lettercount)):
#if the letter is not in dictionary add it
#and set frequency to zero
lettercount[y]=0
#increment the frequency of letter in dictionary
lettercount[y] = lettercount[y]+1
def createoutput(lettercount,wordlist,mostword):
#creates an empty file 'statistics.txt'
try:
txt2=open("statistics.txt",'w+')
except IOError:
print('Unable to create file')
txt2.write('Number of words in the file are '+str(len(wordlist))+'\n')
txt2.write('Most repeated word in the file is '+mostword+'\n')
for x in lettercount:
#write to the file 'statistics.txt'
txt2.write(x+' appeared in the file for '+str(lettercount[x])+' times \n')
def main():
wordlist=getwords()
#lettercount is a dictionary with letters as keys
#and their frequency in the input file as data
lettercount=dict()
mostword=wordcount(wordlist)
letters(wordlist,lettercount)
createoutput(lettercount,wordlist,mostword)
main()

When the open() call fails, you swallow the exception:
try:
global txt
txt=open("sample.txt",'r')
except IOError:
print('Unable to open file')
Now txt is never assigned to, because it is the open() call that fails here. Instead of continuing with the function, you should return at this point:
try:
txt=open("sample.txt",'r')
except IOError:
print('Unable to open file')
return

You want to structure your exceptions like this:
try:
# normal code here
except:
# handle the exception
For example this code is wrong because it runs the code that could fail outside of the exception handler
def createoutput(lettercount,wordlist,mostword):
#creates an empty file 'statistics.txt'
try:
txt2=open("statistics.txt",'w+')
except IOError:
print('Unable to create file')
txt2.write('Number of words in the file are '+str(len(wordlist))+'\n')
txt2.write('Most repeated word in the file is '+mostword+'\n')
Moving the normal read into the exception handler would look like this
def createoutput(lettercount,wordlist,mostword):
#creates an empty file 'statistics.txt'
try:
txt2=open("statistics.txt",'w+')
txt2.write('Number of words in the file are '+str(len(wordlist))+'\n')
txt2.write('Most repeated word in the file is '+mostword+'\n')
except IOError:
print('Unable to create file')
but you never closed the file. Where do you put the close file command? After you opened it obviously, but what happens if txt2.write throws an exception? What if some other problem happens in there? You never close!
With files you will want to do this, so the file is closed when it leaves the scope
with open("statistics.txt", "w+") as statsfile:
statsfile.write("Number of words ...
and of course, you put that in an exception handler
def getwords(filename="sample.txt"):
words = []
try:
with open (filename, 'r') as txt:
for line in txt:
words = words + line.split()
except IOError:
print "unable to open file"
return words

Related

Python NameError exception not working as intended

When I run this code, a NameError traceback error pops up, even though it should be handled by the exception. Why is that?
The function call argument is intentionally misspelled.
filename_cats = "cats.txt"
filename_dogs = "dogs.txt"
def readlines(filename):
"""read lines from a text file"""
try:
with open(filename) as f:
lines = f.readlines()
string = ''
for line in lines:
string += line
except (NameError, FileNotFoundError):
print(f"The file {filename} was not found.")
else:
print(string)
readlines(filename_cat)
It's because the error happens here:
👇
readlines(filename_cat) 👈
☝️
Not anywhere in here:
try:
with open(filename) as f:
lines = f.readlines()
string = ''
for line in lines:
string += line
except (NameError, FileNotFoundError):
A try..except block can only catch errors happening literally within it, not anything happening before or after it.

read/write a file input and insert a string

I need to write function which given a text file object open in read and write mode and a string, inserts the text of the string in the file at the current read/write position. In other words, the function writes the string in the file without overwriting the rest of it. When exiting the function, the new read/write position has to be exactly at the end of the newly inserted string.
The algorithm is simple; the function needs to:
read the content of the file starting at the current read/write position
write the given string at the same position step 1 started
write the content read at step 1. at the position where step 2. ended
reposition the read/write cursor at the same position step2. ended (and step 3. started)
If the argument file object is not readable or writable, the function should print a message and return immediately without changing anything.
This can be achieved by using the methods file object methods readable() and writable().
In the main script:
1- prompt the user for a filename
2- open the file in read-write mode. If the file is not found, print a message and exit the program
3- insert the filename as the first line of the file followed by an empty line
4- insert a line number and a space, at the beginning of each line of the original text.
I'm very confused on how to write the function and main body.
so far I only have
def openFile(fileToread):
print(file.read())
givefile = input("enter a file name: ")
try:
file = open(givefile, "r+")
readWriteFile = openFile(file)
except FileNotFoundError:
print("File does not exist")
exit(1)
print(givefile, "\n")
which is not a lot.
I need an output like this:
twinkle.txt
1 Twinkle, twinkle, little bat!
2 How I wonder what you're at!
3 Up above the world you fly,
4 Like a teatray in the sky.
the file used is a simple .txt file with the twinkle twinkle song
How can I do this?
Basic solution
give_file = input("enter a file name: ")
def open_file(file):
return file.read()
def save_file(file, content):
file.write(content)
try:
# Use this to get the data of the file
with open(give_file, "r") as fd:
file_content = open_file(fd)
except FileNotFoundError:
print("File does not exist")
exit(1)
# change the data
new_content = f'{give_file}\n\n{file_content}'
try:
# save the data
with open(give_file, "w") as fd:
save_file(fd, new_content)
except FileNotFoundError:
print("File does not exist")
exit(1)
This should give you the expected result.
I asked about the r+ and how to use it in this case. I got this answer:
reset the cursor to 0 should do the trick
my_fabulous_useless_string = 'POUET'
with open(path, 'r+') as fd:
content = fd.read()
fd.seek(0)
fd.write(f'{my_fabulous_useless_string}\n{content}')
so with your code it's:
give_file = input("enter a file name: ")
def open_file(file):
return file.read()
def save_file(file, content):
file.write(content)
try:
# Use this to get the data of the file
with open(give_file, "+r") as fd:
file_content = open_file(fd)
new_content = f'{give_file}\n\n{file_content}'
fd.seek(0)
save_file(fd, new_content)
except FileNotFoundError:
print("File does not exist")
exit(1)
A suggestion
Don't use function, it hide the fact that a method is used with some side-effects (move the cursor).
Instead, call the method directly, this is better:
give_file = input("enter a file name: ")
try:
# Use this to get the data of the file
with open(give_file, "+r") as fd:
file_content = fd.read()
new_content = f'{give_file}\n\n{file_content}'
fd.seek(0)
fd.write(new_content)
except FileNotFoundError:
print("File does not exist")
exit(1)
Or, with the basic solution and functions
def open_file(path):
with open(path, "r") as fd:
return fd.read()
def save_file(path, content):
with open(path, 'w') as fd:
fd.write(content)
# get file_name
file_name = input("enter a file name: ")
try:
# Use this to get the data of the file
file_content = open_file(file_name)
except FileNotFoundError:
print("File does not exist")
exit(1)
# change the data
new_content = f'{file_name}\n\n{file_content}'
# save the data
save_file(file_name, new_content)

How can I iterate through a file and raise a custom Exception if there is not enough input?

I have been following the 'Python for dummies' book and there is one example that doesn't print out the result as I expected.
class Error(Exception):
pass
class NotEnoughStuffError(Error):
pass
try:
thefile = open('people.csv')
line_count = len(thefile.readlines())
if line_count < 2:
raise NotEnoughStuffError
except NotEnoughStuffError:
print('Not Enough Stuff')
except FileNotFoundError:
print('File not found')
thefile.close()
else:
for line in thefile:
print(line)
thefile.close()
print('Success!')
Question 1: When it prints, it should show all the lines from thefile. However, it only prints 'Success!' Why the content from thefile was not printed?
Question 2: I replaced the code:
class Error(Exception):
pass
class NotEnoughStuffError(Error):
pass
with
class NotEnoughStuffError(Exception):
pass
Do they return the same result? Is 'Exception' a built-in class in Python?
Problem is because you used readlines() and it moved pointer to the end of file and when you later use for line in thefile: then it tries to read from end of file. And it reads nothing from the end of file and it display nothing.
You would have assing list with lines to variable
all_lines = thefile.readlines()
line_count = len(all_lines)
and later use this list
for line in all_lines:
print(line)
Or you would have to move pointer to the beginning of file before you try to read again data
thefile.seek(0)
for line in thefile:
print(line)

How to print a text file in python

I'm fairly new to coding and am having some issues printing a text file.
Here's my file:
Player1: 1
Player2: 3
Here's my code:
try:
scoreTable = open("scoreTable.txt", "r")
line = scoreTable.readlines()
for i in range(0, (len(line))):
print(scoreTable.read(len(line[i].strip("\n"))))
scoreTable.close()
except FileNotFoundError:
pass
At the moment its just printing whitespace.
I'm probably missing something obvious or have gone down the wrong road altogether, so any help would be appreciated.
Thanks in advance.
Just use the below code sample to print the whole file.
try:
with open("scoreTable.txt", "r" ) as scoreTable:
file_content = scoreTable.read()
print str(file_content)
except FileNotFoundError as e:
print e.message
You are performing read operation on scoreTable.txt twice, which is not required.
try:
scoreTable = open("scoreTable.txt", "r")
lines = scoreTable.readlines()
#here in lines you have whole file stored so no need to try to read from files variable again
for line in lines:
print line
scoreTable.close()
except FileNotFoundError:
pass
While we are on this subject use with statement to read files(so you wont have to keep track to close the file)
with open("scoreTable.txt", "r" ) as f:
lines = f.readlines()
for line in lines:
print line

UnpicklingError: Invalid load key'(heart)'

I've been messing around with pickle for some days, trying to apply it in a High Score system in a 'Guess the number' exercise program. I thought that I had grasped the concept correctly, but now this error has appeared and I have no clue as to why.
Here's the relevant code:
def EnterHighScore(score,scoresList):
name = input("Enter your name: ")
newPlayer = player(name,score)
scoresList.append(newPlayer)
scoresFile = open('scores','wb')
pickle.dump(scoresList,scoresFile)
scoresFile.close()
for i in scoresList:
print(i.name + ' - ' + str(i.score))
def CheckHighScores(score):
try:
scoresFile = open('scores','rb')
except:
scoresFile = open('scores','wb+')
if not scoresFile.read(1):
scoresList = []
else:
scoresList = pickle.load(scoresFile)
scoresFile.close()
if not scoresList:
EnterHighScore(score,scoresList)
else:
for counter,i in enumerate(scoresList):
if counter == 3:
break
if score >= i.score:
EnterHighScore(score,scoresList)
break
When I run it, the first run through goes fine. That is, when the 'scores' file doesn't even exist. It gets created correctly, the scoresList is created empty and then filled with a player object and it gets dumped into the scoresFile without any errors. But when I try to load the scoresList with the new 'scores' file data, it gives me the following error:
UnpicklingError: Invalid load key'(heart)'
(heart) standing for an actual heart character.
I've read that others have had this problem, but in those cases they were trying to open the file in different OS's, or had modified the file in some way after pickling but before unpickling. In this case the file hasn't been modified at all, just written to and closed.
I've tried using pickle in other, simpler scenarios, and I haven't caused other errors.
Any help will be appreciated.
Your test to see if the file is empty advances the file read pointer past the start of the file:
if not scoresFile.read(1):
You'll have to seek back to the beginning:
if not scoresFile.read(1):
scoresList = []
else:
scoresFile.seek(0)
scoresList = pickle.load(scoresFile)
A much better test would be for you to catch the EOFError exception that pickle.load() throws if the file is empty:
try:
scoresList = pickle.load(scoresFile)
except EOFError:
# File empty
scoresList = []
Or you could catch the IOError when the file doesn't exist:
try:
with open('scores','rb') as scoresFile:
scoresList = pickle.load(scoresFile)
except IOError:
scoresList = []
and just not open a file for writing here.

Categories