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.
Related
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)
I'm trying to do my project for class and keep getting this error when I try and run it.
try:
^ IndentationError: unindent does not match any outer indentation
level
Here is my code:
author=''
try:
fh = open( sys.argv[0], encoding="utf8")
for line in fh:
m = re.search('# *AUTHOR: *([\w\-]+ *[\w\-]+)', line)
if m is not None:
author = m.group(1)
except( IOError, OSError) as err:
print(err)
return ''
finally:
if fh is not None:
fh.close()
return author.lower()
As people said, you cannot have a condition/loop/expect or any kind of block that has nothing after it.
If you want to catch the error, but do nothing with it, just add pass (with the right indentation of course).
author=''
try:
fh = open( sys.argv[0], encoding="utf8")
for line in fh:
m = re.search('# *AUTHOR: *([\w\-]+ *[\w\-]+)', line)
if m is not None:
author = m.group(1)
except( IOError, OSError) as err:
# Do something here or pass
pass
Also, adding nothing but comments is equivalent to adding nothing at all. Therefore this will give you the same error:
except( IOError, OSError) as err:
# I want to do nothing
I was trying to improve my friend's Python 'Twitch account checker' (basically gets a list of usernames from a text file and checks if they're available or taken on Twitch.tv). I was going to improve it in a way that it would output the available usernames into a text file (in the same location as the original list). I was actually searching Stack Overflow and found a post which 'explained' how to actually output a list (I put the available usernames into a separate list) into a text file.
When running the script, it works fine up to the part where it's supposed to save the available usernames. Then, I get the following error:
Traceback (most recent call last):
File "multithreadtwitchchecker.py", line 44, in <module>
output_available_usernames('availableusernames.txt')
File "multithreadtwitchchecker.py", line 37, in output_available_usernames
AVAILABLE_USERNAMES = f.write(AVAILABLE_USERNAMES.split('\n'))
AttributeError: 'list' object has no attribute 'split'
Here's the code:
from multiprocessing.pool import ThreadPool
import re
import requests
import sys
try:
input = raw_input
except NameError:
pass
TWITCH_URL = "https://www.twitch.tv/{username}"
TWITCH_REGEX = re.compile(r"^[a-zA-Z0-9_]{4,25}$")
MAX_THREADS = 25
MESSAGES = {True: "Available", False: "Taken"}
AVAILABLE_USERNAMES = []
def read_valid_usernames(filename):
"""Reads a list of usernames and filters out invalid ones."""
try:
with open(filename, "r") as fin:
return [username for username in map(str.strip, fin) if TWITCH_REGEX.match(username)]
except IOError:
sys.exit("[!] '{}' - Invalid File".format(filename))
def username_available(username):
"""Checks if a 404 response code is given when requesting the profile. If it is, it is presumed to be available"""
try:
return username, requests.get(TWITCH_URL.format(username=username)).status_code == 404
AVAILABLE_USERNAMES.append(username)
except Exception as e:
print(e)
def output_available_usernames(filename):
"""Gets a filename to output to and outputs all the valid usernames to it"""
global AVAILABLE_USERNAMES
f = open(filename, 'w')
AVAILABLE_USERNAMES = f.write(AVAILABLE_USERNAMES.split('\n'))
usernames = read_valid_usernames(input("Enter path to list of usernames: "))
for username, available in ThreadPool(MAX_THREADS).imap_unordered(username_available, usernames):
print("{:<{size}}{}".format(username, MESSAGES.get(available, "Unknown"), size=len(max(usernames, key=len)) + 1))
output_available_usernames('availableusernames.txt')
Well, writing to a file can be done like this:
def output_available_usernames(filename):
global AVAILABLE_USERNAMES
with open(filename, 'w') as f:
for name in AVAILABLE_USERNAMES:
f.write(name + '\n')
As jonrsharpe said, split is going in the wrong direction.
However, your code has a deeper problem right now. You append to AVAILABLE_USERNAMES after the return statement, so that code never executes, and AVAILABLE_USERNAMES will always be empty. You instead want something like this:
def username_available(username):
"""Checks if a 404 response code is given when requesting the profile. If it is, it is presumed to be available"""
try:
if requests.get(TWITCH_URL.format(username=username)).status_code == 404:
AVAILABLE_USERNAMES.append(username)
return username, True
else:
return username, False
except Exception as e:
print(e)
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
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