Why my python code is showing value error? - python

I am writing this python code to check DNA sequence file. The output will be the name of person to whom this DNA is matched.
This link has the description of assignment.
https://cs50.harvard.edu/x/2020/psets/6/dna/
But when i try to run the code its showing value error.
Kindly someone let me know the error in the code.
I am new to the programming.
from sys import argv, exit
import csv
def max_Reptitions_of_substrings(dnaSequences , substring):
arr = [0] * len(dnaSequences)
for i in range(len(dnaSequences) - len(substring), -1, -1):
if dnaSequences[i: i + len(substring)] == substring:
if i + len(substring) > len(dnaSequences) - 1:
arr[i] = 1
else:
arr[i] = 1 + arr[i + len(substring)]
return max(arr)
def print_Matching(reading, newdata):
for i in reading:
human = i[0]
value = [int(digit) for digit in i[1:]]
if value == newdata:
print(human)
return
print("No match")
def main():
if len(argv) != 3:
print("Missing Command line Argument")
exit(1)
with open(argv[1], 'r') as database:
reading = csv.reader(database)
sequences = next(reading)[1:]
with open(argv[2], 'r') as sequenceFilestrong text:
dnaSequences = sequenceFile.read()
newdata = [max_Reptitions_of_substrings(dnaSequences, substr) for substr in sequences]
print_Matching(reading, newdata)
Value error shown is as
Traceback (most recent call last):
File "dna.py", line 36, in <module>
print_Matching(reading, newdata)
File "dna.py", line 15, in print_Matching
for i in reading:
ValueError: I/O operation on closed file.

The error message is pretty explicit and spot-on:
ValueError: I/O operation on closed file.
You are opening your CSV file in a with block and create a new CSV reader based on that file. But at the end of the with block, the file is closed. reading now refers to a CSV reader that’s linked to a closed file connection.
Hence the error.

Try to look at code indentation, it's very important in Python. First with should be inside function main, second with should be inside first with.
Why?
Just look at the code. In print matching you're using reading csv.reader, which right now try to use already closed file passed as argument.

Related

Reading and adding numbers from a text document in Python

I have a text document with a list of numbers, I need to have a function that reads all of them, and adds them together so then I can average them all out. I'm able to print the individual numbers and count the total numbers but not add the actual numbers together. Currently my code gives me "ValueError: invalid literal for int() with base 10: ''"
def CalcAverage():
scoresFile = open("data.txt", "r")
line = scoresFile.readline()
scoreCounter = 1
scoreTotal = 0
while line != "":
line = scoresFile.readline()
total = int(line) + int(line)
scoreCounter = int(scoreCounter) + 1
print(total)
scoresFile.close()
Assuming this is the error you're getting, replicated in the REPL:
>>> int("")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''
Then the issue is that you're trying to cast an empty string into an int. This will naturally result in an error, and is a common one if you have empty lines in your file.
You sorta check against this:
while line != "":
But the issue with this is where you assign line: immediately after this check. While your first line value will be checked, it will be immediately replaced by a new line = scoresFile.readline().
Thus, as you enter your while loop, line is the first line in your file. Then, it will assign the second line to line, dropping the first line's value. This will cause two different errors - one where you attempt in the following line to cast an empty string to an int, and one where you are ignoring the value of your first line. You need to alter how you do your check.
def calc_average():
with open("data.txt", "r") as scores:
counter = 0
total = 0
for line in scores.readlines(): # Returns the lines as a list
total += int(line)
counter += 1
print(f"{total=} {counter=}")
Note these following good-hygeine practices in Python:
Name your variables and functions using snake case.
Use with to open a file. This calls close automatically, so you don't risk forgetting it.

Why we can't print particular line of text file with this method? [duplicate]

The main function that the code should do is to open a file and get the median. This is my code:
def medianStrat(lst):
count = 0
test = []
for line in lst:
test += line.split()
for i in lst:
count = count +1
if count % 2 == 0:
x = count//2
y = lst[x]
z = lst[x-1]
median = (y + z)/2
return median
if count %2 == 1:
x = (count-1)//2
return lst[x] # Where the problem persists
def main():
lst = open(input("Input file name: "), "r")
print(medianStrat(lst))
Here is the error I get:
Traceback (most recent call last):
File "C:/Users/honte_000/PycharmProjects/Comp Sci/2015/2015/storelocation.py", line 30, in <module>
main()
File "C:/Users/honte_000/PycharmProjects/Comp Sci/2015/2015/storelocation.py", line 28, in main
print(medianStrat(lst))
File "C:/Users/honte_000/PycharmProjects/Comp Sci/2015/2015/storelocation.py", line 24, in medianStrat
return lst[x]
TypeError: '_io.TextIOWrapper' object is not subscriptable
I know lst[x] is causing this problem but not too sure how to solve this one.
So what could be the solution to this problem or what could be done instead to make the code work?
You can't index (__getitem__) a _io.TextIOWrapper object. What you can do is work with a list of lines. Try this in your code:
lst = open(input("Input file name: "), "r").readlines()
Also, you aren't closing the file object, this would be better:
with open(input("Input file name: ", "r") as lst:
print(medianStrat(lst.readlines()))
with ensures that file get closed.
basic error my end, sharing in case anyone else finds it useful. Difference between datatypes is really important! just because it looks like JSON doesn't mean it is JSON - I ended up on this answer, learning this the hard way.
Opening the IO Stream needs to be converted using the python json.load method, before it is a dict data type, otherwise it is still a string. Now it is in a dict it can be brought into a dataFrame.
def load_json(): # this function loads json and returns it as a dataframe
with open("1lumen.com.json", "r") as io_str:
data = json.load(io_str)
df = pd.DataFrame.from_dict(data)
logging.info(df.columns.tolist())
return(df)

index out of range raises in random function [duplicate]

This question already has answers here:
f.read coming up empty
(5 answers)
Closed 7 years ago.
I have this function which simply opens a text files and read lines:
def select_word(model):
lines = model.read().splitlines()
selectedline = random.choice(lines)
return [selectedline.split(":")[0],selectedline.split(":")[1]]
when I call this function for just one, there is no problem. But when I call it more than once:
print select_word(a)
print select_word(a)
print select_word(a)
print select_word(a)
print select_word(a)
I got this error:
Traceback (most recent call last):
File "wordselect.py", line 58, in <module>
print select_word("noun")
File "wordselect.py", line 19, in select_word
selectedline = random.choice(lines)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/random.py", line 275, in choice
return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
IndexError: list index out of range
What is the problem with that function?
import random
def select_word(model):
with open(model, 'r') as f:
lines = f.read().splitlines()
selectedline = random.choice(lines)
return [selectedline.split(":")[0],selectedline.split(":")[1]]
result = select_word('example.txt')
print result
I did this and didnt get a problem.
just make sure that in the file you are opening you have something like.
Line: 1
Line: 2
random.choice raises IndexError if you pass it an empty sequence. This happens when you call .read() on a file object the second time (you can only do it once, subsequent calls will return an empty string).
To fix the function, you could read the file once then pass the lines to the function, e.g.:
lines = list(model)
def select_word(lines):
selectedline = random.choice(lines)
return selectedline.split(":", 1)
File handles operate like generators. Once you have read a file, you have reached the end of stream.
model.seek(0) # bring cursor to start of file after reading, at 2nd line of the function

Python read file from the end, it's a large file,cannot read into memory [duplicate]

This question already has answers here:
How to read lines from a file in python starting from the end
(5 answers)
Closed 9 years ago.
How to read the file from the file at the end DESC?
For example
filename:test
content:
11111111
22222222
333333333
fp = open('test', 'r')
print fp.readline
333333333
22222222
11111111
it is a large file,i do not want to read all content out.
Instead of Reading line from the end which is relatively tidious process,
you can use reversed() function as follows..
with open(filename, 'r') as fheader:
for line in reversed(fheader.readlines()):
print line
Hope this helps :)
for x in open(r'C:\test.txt').readlines()[::-1]:
print x
We discussed the same problem in the China Python User Group just a few month ago. The some of the answers are copied from our discussion.
No matter what solution you choose, the essential is same: seek to the end of the file, read a block of data, find the last line breaker(\r\n or \n), get the last line, seek backwards, and do the same thing again and again.
You can try to preprocess the file with tail -n, it is efficient(implemented in C) and is designed for this job.
Check its source code if you want to implement it yourself.
or call the same command in Python:
from subprocess import Popen, PIPE
txt = Popen(['tail', '-n%d' % n, filename], stdout=PIPE).communitate()[0]
;)
or try a pure python solution:
def last_lines(filename, lines = 1):
#print the last several line(s) of a text file
"""
Argument filename is the name of the file to print.
Argument lines is the number of lines to print from last.
"""
block_size = 1024
block = ''
nl_count = 0
start = 0
fsock = file(filename, 'rU')
try:
#seek to end
fsock.seek(0, 2)
#get seek position
curpos = fsock.tell()
while(curpos > 0): #while not BOF
#seek ahead block_size+the length of last read block
curpos -= (block_size + len(block));
if curpos < 0: curpos = 0
fsock.seek(curpos)
#read to end
block = fsock.read()
nl_count = block.count('\n')
#if read enough(more)
if nl_count >= lines: break
#get the exact start position
for n in range(nl_count-lines+1):
start = block.find('\n', start)+1
finally:
fsock.close()
#print it out
print block[start:]
if __name__ == '__main__':
import sys
last_lines(sys.argv[0], 5) #print the last 5 lines of THIS file

Python 2.7 using if elif to go through a text file

Goal is to write a script which will copy a text file and exclude any line beginning with #.
My question is I seem to get an index error which is dependent upon the order of my if elif conditions. The only difference between the nonworking code and the working code (besides the suffix "_bad" to the nonworking function name) is that I test the "" condition first (works) vs testing the "#" condition first (doesn't work)
Base file is created by this script:
>>> testFileObj = open("test.dat","w")
>>> testFileObj.write("#line one\nline one\n#line two\nline two\n")
>>> testFileObj.close()
Code which works:
def copyAndWriteExcludingPoundSigns(origFile, origFileWithOutPounds):
origFileObj = open(origFile,"r")
modFileObj = open(origFileWithOutPounds,"w")
while True:
textObj = origFileObj.readline()
if textObj == "":
break
elif textObj[0] == "#":
continue
else:
modFileObj.write(textObj)
origFileObj.close()
modFileObj.close()
Code which doesn't work:
def copyAndWriteExcludingPoundSigns_Bad(origFile, origFileWithOutPounds):
origFileObj = open(origFile,"r")
modFileObj = open(origFileWithOutPounds,"w")
while True:
textObj = origFileObj.readline()
if textObj[0] == "#":
continue
elif textObj == "":
break
else:
modFileObj.write(textObj)
origFileObj.close()
modFileObj.close()
Which gives me this error:
Traceback (most recent call last):
File "<pyshell#96>", line 1, in <module>
copyAndWriteExcludingPoundSigns_Bad("test.dat","testOutput.dat")
File "<pyshell#94>", line 6, in copyAndWriteExcludingPoundSigns_Bad
if textObj[0] == "#":
IndexError: string index out of range
If you do if textObj[0] == "#": and textObj="" then there is no character at the zero index, because the string is empty, hence the index error.
The alternative is to do
if textObj.startswith("#"): which will work in both cases.
some tips (and please please read PEP8):
use a 'for' instead of a 'while' loop
no need to use readlines after python 2.4
test if the line is empty before testing for the first char
Untested:
def copy_and_write_excluding_pound_signs(original, filtered):
original_file = open(original,"r")
filtered_file = open(filtered,"w")
for line in original_file:
if line and line[0] == '#':
continue
filtered_file.write(line)
original_file.close()
filtered_file.close()
You may also want to filter a line with some white space befor the '#':
import re
def copy_and_write_excluding_pound_signs(original, filtered):
pound_re = re.compile(r'^\s*#')
original_file = open(original,"r")
filtered_file = open(filtered,"w")
for line in original_file:
if pound_re.match(line):
continue
filtered_file.write(line)
original_file.close()
filtered_file.close()
You should use line.startswith('#') to check whether the string line starts with '#'. If the line is empty (such as line = ''), there would be no first character, and you'd get this error.
Also the existence of a line that an empty string isn't guaranteed, so breaking out of the loop like that is inadvisable. Files in Python are iterable, so can simply do a for line in file: loop.
The problem with your non-working code is that it is encountering an empty line, which is causing the IndexError when the statement if textObj[0] == "#": is evaluated ([0] is a reference to the first element of string). The working code avoids doing that when the line is empty.
The simpliest way I can think of to rewrite your function is to use for line in <fileobj> you won't have worry about line ever being empty. Also if you use the Python with statement, your files will also automatically be closed. Anyway here's what I suggest:
def copyAndWriteExcludingPoundSigns(origFile, origFileWithOutPounds):
with open(origFile,"r") as origFileObj:
with open(origFileWithOutPounds,"w") as modFileObj:
for line in origFileObj:
if line[0] != '#':
modFileObj.write(line)
The two with statement could be combine, but that would have made for a very long and harder to read line of code so I broke it up.

Categories