Program doesn't stop iterating through list - python-3.x

def gameinfo():
lines = []
html_doc = 'STATIC.html'
soup = BeautifulSoup(open(html_doc), 'html.parser')
for mytable in soup.find_all('table'):
for trs in mytable.find_all('tr'):
tds = trs.find_all('td')
row1 = [elem.text.strip() for elem in tds]
row = str(row1)
sausage = False
with open("FIRE.txt", "r+") as file:
for line in file:
if row+"\n" in line:
break
else:
if row.split(",")[:4] == line.split(",")[:4]:
print(row)
print(line)
file.write(line.replace(line+"\n", row+"\n"))
print('Already exists with diff date')
sausage = True
break
if sausage == False:
print(row.split(",")[:4])
print(line.split(",")[:4])
print(row)
print(line)
file.write(row+"\n")
print('appended')
while True:
gameinfo()
gameinfo()
This program is supposed to keep searching the text file FIRE.txt for lines that match the variable row. When i run it, it works okay, but the part of the code that is supposed to check if the first four elements of the list are the same, and then skin the appending section below, doesn't work. When the program detects that the first 4 elements of a string turned into a list(row) that matches with another string's first 4 elements that's in the text file, it should overwrite the string in the text file. However when it detects a list that has the same first 4 elements, it loops forever and never breaks out.
My string looks like this:
['Infield Upper Deck Reserved 529', '$17.29', '4', '2', '175']
and i compare it to a list that looks like this:
['Infield Upper Deck Reserved 529', '$17.29', '4', '2', '170']
and when it sees that the first 4 elements in the list are the same, it should overwrite the one that was in the text file to begin with, but it is looping.

Question has changed; most recent version last.
Methinks you want to use the csv module. If you iterate through a csv.reader object instead of the file object directly, you'll get each line as a a list.
Example:
import csv
row = ["this", "is", "an", "example"]
with open("FIRE.txt", "r+") as file:
reader = csv.reader(file)
for line in reader:
if row in line:
break
pass
Alternatively, if you don't need to use this in anything other than Python, you could pickle a collections.OrderedDict with a tuple of the first four items as the keys:
import collections
import pickle
import contextlib
#contextlib.contextmanager
def mutable_pickle(path, default=object):
try:
with open(path, "rb") as f:
obj = pickle.load(f)
except IOError, EOFError:
obj = default()
try:
yield obj
finally:
with open(path, "wb") as f:
pickle.dump(obj, f)
with mutable_pickle("fire.bin",
default=collections.OrderedDict) as d:
for row in rows:
d[tuple(row[:4])] = row

Related

read and write from and to file using functions

I'm trying to create 2 functions.
readfiles(file_path), That reads a file specified by file_path and returns a list of strings containing each line in the file.
writefiles(lines, file_path) That writes line by line the content of the list lines to the file specified by file_path.
When used one after another the output file should be an exact copy of the input file(including the formatting)
This is what i have so far.
file_path = ("/myfolder/text.txt", "r")
def readfiles(file_path):
with open file_path as f:
for line in f:
return line
lst = list[]
lst = line
lst.append(line)
return lst
read_file(file_path)
lines = lst []
def writefiles(lines, file_path):
with open ("file_path", "w") as f:
for line in lst:
f.write(line)
f.write("\n")
I can get it to kind of work when I use this for read
with open("/myfolder/text.txt", "r") as f:
for line in f:
print(line, end='')
and this for write
with open ("/myfolder/text.txt", "w") as f:
for line in f:
f.write(line)
f.write("\n")
But when I try to put them into functions it all messes up.
I'm not sure why, I know it's a simple question but it's just not clicking for me. I've read documentation on it but I'm not following it fully and am at my wits end. What's wrong with my functions?
I get varying errors from
lst = list[]
^
SyntaxError: invalid syntax
to
lst or list is not callable
Also I know there are similar questions but the ones I found don't seem to define a function.
The problems with your code are explained as comments
file_path = ("/myfolder/text.txt", "r") # this is a tupple of 2 elements should be file_path = "/myfolder/text.txt"
def readfiles(file_path):
with open file_path as f: # "open" is a function and will probably throw an error if you use it without parenthesis
# use open this way: open(file_path, "r")
for line in f:
return line # it will return the first line and exit the function
lst = list[] # "lst = []" is how you define a list in python. also you want to define it outside the loop
lst = line # you are replacing the list lst with the string in line
lst.append(line) # will throw an error because lst is a string now and doesn't have the append method
return lst
read_file(file_path) # should be lines = read_file(file_path)
lines = lst [] # lines is an empty list
def writefiles(lines, file_path):
with open ("file_path", "w") as f:
for line in lst: # this line should have 1 more tabulation
f.write(line) # this line should have 1 more tabulation
f.write("\n") # this line should have 1 more tabulation
Here's how the code should look like
def readfiles(file_path):
lst = []
with open(file_path) as f:
for line in f:
lst.append(line.strip("\n"))
return lst
def writefiles(lines, file_path):
with open(file_path, "w") as f:
for line in lines:
f.write(line + "\n")
file_path = "/myfolder/text.txt"
filepathout = "myfolder/text2.txt"
lines = readfiles(file_path)
writefiles(lines, filepathout)
A more pythonic way to do it
# readlines is a built-in function in python
with open(file_path) as f:
lines = f.readlines()
# stripping line returns
lines = [line.strip("\n") for line in lines]
# join will convert the list to a string by adding a \n between the list elements
with open(filepathout, "w") as f:
f.write("\n".join(lines))
key points:
- the function stops after reaching the return statement
- be careful where you define your variable.
i.e "lst" in a for loop will get redefined after each iteration
defining variables:
- for a list: list_var = []
- for a tuple: tup_var = (1, 2)
- for an int: int_var = 3
- for a dictionary: dict_var = {}
- for a string: string_var = "test"
A couple learning points here that will help.
In your reading function, you are kinda close. However, you cannot put the return statement in the loop. As soon as the function hits that anywhere for the first time, it ends. Also, if you are going to make a container to hold the list of things read, you need to make that before you start your loop. Lastly, don't name anything list. It is a keyword. If you want to make a new list item, just do something like: results = list() or results = []
So in pseudocode, you should:
Make a list to hold results
Open the file as you are now
Make a loop to loop through lines
append to the results list
return the results (outside the loop)
Your writefiles is very close. You should be looping through the lines variable that is a parameter of your function. Right now you are referencing lst which is not a parameter of your function.
Good luck!

Getting an IndexError: list index out of range in line no. = 19?

import csv
with open('C:/Users/dkarar/Desktop/Mapping project/RC_Mapping.csv', 'r') as file1:
with open('C:/Users/dkarar/Desktop/Mapping project/Thinclient_mapping.csv', 'r') as file2:
with open('C:/Users/dkarar/Desktop/Mapping project/output.csv', 'w') as outfile:
writer = csv.writer(outfile)
reader1 = csv.reader(file1)
reader2 = csv.reader(file2)
for row in reader1:
if not row:
continue
for other_row in reader2:
if not other_row:
continue
# if we found a match, let's write it to the csv file with the id appended
if row[1].lower() == other_row[1].lower():
new_row = other_row
new_row.append(row[0])
writer.writerow(new_row)
continue
# reset file pointer to beginning of file
file2.seek(0)
You seem to be getting at least one row where there is a single element. That's why when accessing row[1] you get an IndexError, there's only one element in the list row.

write the output of the code on a CSV file

I have a csv file a list of name and mean.
For example:
ali,5.0
hamid,6.066666666666666
mandana,7.5
soheila,7.833333333333333
sara,9.75
sina,11.285714285714286
sarvin,11.375
I am going to rewrite the csv by three lower mean. I have write the code, but I have a problem to write the csv again. I should keep the mean number exactly as an input.
import csv
import itertools
from collections import OrderedDict
with open ('grades4.csv', 'r') as input_file:
reader=csv.reader(input_file)
val1=[]
key=list()
threelowval=[]
for row in reader:
k = row[0]
val=[num for num in row[1:]] #seperate a number in every row
key.append(k) #making a name -key- list
val1.append(val) #making a value list
value = list(itertools.chain.from_iterable(val1)) #making a simple list from list of list in value
value=[float(i) for i in value] ##changing string to float in values
#print(key)
#print(value)
dictionary = dict(zip(key, value))
#print(dictionary)
findic=OrderedDict(sorted(dictionary.items(), key=lambda t: t[1])) ##making a sorted list by OrderedDict
#print(findic)
##make a separation for the final dict to derive the three lower mean
lv=[]
for item in findic.values():
lv.append(item)
#print(lv)
for item in lv[0:3]:
threelowval.append(item)
print(threelowval)
I have tried below code but I get the error.
with open('grades4.csv', 'w', newline='') as output_file_name:
writer = csv.writer(output_file_name)
writer.writerows(threelowval)
expected result:
5.0
6.066666666666666
7.5
You should try this:
with open('grades4.csv', 'w', newline='') as output_file_name:
writer = csv.writer(output_file_name)
for i in threelowval:
writer.writerow([i])
I have tried below code and receive the correct results.
with open('grades4.csv', 'w', newline='') as output_file_name:
writer = csv.writer(output_file_name)
writer.writerows(map(lambda x: [x], threelowval))

How to add numbers in Text file with Strings [duplicate]

This question already has an answer here:
How to perform addition in text file bypassing strings
(1 answer)
Closed 4 years ago.
import csv
csv_file = 'Annual Budget.csv'
txt_file = 'annual_budget.txt'
with open(txt_file, 'w') as my_output_file:
with open(csv_file, 'r') as my_input_file:
reader = csv.reader(my_input_file)
for row in reader:
my_output_file.write(" ".join(row)+'\n')
data = []
with open(r'annual_budget.txt', 'r') as f:
reader = csv.reader(f)
header = next(reader)
for line in reader:
rowdata = map(float, line)
data.extend(rowdata)
print(sum(data)/len(data))
Trying to add the numbers in a text file with strings but error is continually thrown.
Output:
data.extend(rowdata)
ValueError: could not convert string to float:
Data Set: [1]: https://i.stack.imgur.com/xON30.png
TLDR: You're treating space delimited text as csv which is not parsing correctly by the csv module.
At the time I worked this problem out for you, you had not provided origional csv data, so for this problem I assumed your csv file contained the following data, based on your screenshot of the txt file.
Annual Budget,Q2,Q4
100,450,20
600,765,50
500,380,79
800,480,455
1100,65,4320
Now, about the code.
You're defining data = [] in a place where it is not only
not used, but also causing it to be reset to an empty
list with every loop through the file you're converting.
If we add a print statement directly under it we get this for output:
showing added print statement:
with open(txt_file, 'w') as my_output_file:
with open(csv_file, 'r') as my_input_file:
reader = csv.reader(my_input_file)
for row in reader:
my_output_file.write(" ".join(row)+'\n')
data = []
print(data)
Output:
[]
[]
[]
[]
[]
[]
Moving data = [] to the top of the file prevents that.
Now with the second with statement and loops you're treating the txt file you just created as a csv file. csv data is comma delimited not space delimited. The csv reader isn't parsing the row correctly. if we add a print loop to check what is coming out of the map function we can see it's not doing what you're expecting it to, which is convert it to a list of floats.
Relevent code:
for line in reader:
rowdata = map(float, line)
for element in rowdata:
print(element)
output:
Traceback (most recent call last):
File "test.py", line 17, in <module>
for element in rowdata:
ValueError: could not convert string to float: '100 450 20'
There are multiple ways to solve the problem, but I think the best is to simply skip the whole first loop where you convert it to a space delimited file. Doing so we just depend on the csv module to do it's job.
example code:
import csv
data = []
with open('Annual Budget.csv', 'r') as f:
reader = csv.reader(f) # Gets the reader
header = next(reader) # advance the reader past the header.
for line in reader:
rowdata = map(float, line)
for element in rowdata:
print(element)
Output:
100.0
450.0
20.0
600.0
765.0
50.0
500.0
380.0
79.0
800.0
480.0
455.0
1100.0
65.0
4320.0
Now we'll add your last couple lines of code back in and remove the test code:
import csv
data = []
with open('Annual Budget.csv', 'r') as f:
reader = csv.reader(f) # Gets the reader
header = next(reader) # advance the reader past the header.
for line in reader:
rowdata = map(float, line)
data.extend(rowdata)
print(sum(data)/len(data))
Which now outputs:
677.6

Removing empty lists from csv file in Python 3

I have been working on code that takes rows from csv file and transfer them into the lists of integers for further mathematical operations. However, if a row turns out to be empty, it causes problems. Also, the user will not know which row is empty, so the solution should be general rather than pointing at a row and removing it. Here is the code:
import csv
import statistics as st
def RepresentsInt(i):
try:
int(i)
return True
except ValueError:
return False
l = []
with open('Test.csv', 'r') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
l.append([int(r) if RepresentsInt(r) else 0 for r in row])
for row in l:
row=[x for x in row if x!=0]
row.sort()
print(row)
I've tried l=[row for row in l if row!=[]] and ...
if row==[]:
l.remove(row)
... but both do nothing, and there is no error code for either. Here is my csv file:
1,2,5,4
2,3
43,65,34,56,7
0,5
7,8,9,6,5
33,45,65,4
If I run the code, I will get [] for row 4 and 6 (which are empty).
This worked on my machine:
import csv
def RepresentsInt(i):
try:
int(i)
return True
except ValueError:
return False
l = []
with open('Test.csv', 'r') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
l.append([int(r) for r in row if RepresentsInt(r)])
rows = [row for row in l if row]
for row in rows:
print(row)
It is unclear what you are doing with the statistics module, but the following program should you what you asked for. The pprint module is imported to make displaying the generated table easier to read. If this answer solves the problem presented in your question but you are having difficulty somewhere else, make sure you open another question targeted at the new problem.
#! /usr/bin/env python3
import csv
import pprint
def main():
table = []
# Add rows to table.
with open('Test.csv', newline='') as file:
table.extend(csv.reader(file))
# Convert table cells to numbers.
for index, row in enumerate(table):
table[index] = [int(value) if value.isdigit() else 0 for value in row]
# Remove zeros from the rows.
for index, row in enumerate(table):
table[index] = [value for value in row if value]
# Remove empty rows and display the table.
table = [row for row in table if row]
pprint.pprint(table)
if __name__ == '__main__':
main()

Resources