Failure while trying to append in a try statement - python

So I have a small program that reads a file and creates it if it doesn't exist.
But it fails when you try to read the contents of the second and third file and append it to the first.
I marked in the code exactly where it fails.
It always jumps to the except part, I didnt include it here because it seemed unnecesary (the except part)
with open ('lista1.txt','r') as file_1:
reader_0 = file_1.readlines() #reads a list of searchterms, the first search term of this list is "gt-710"
for search in reader_0:
# creates the txt string component of the file to be created, this is the first one
file_0 = search.replace("\n","") +".txt"
file_1 = str(file_0.strip())
# creates the txt string component of the file to be created, this is the second one
files_2 = search.replace("\n","") +"2.txt"
file_2 = str(files_2.strip())
# creates the txt string component of the file to be created, this is the second one
files_3 = search.replace("\n","") +"3.txt"
file_3 = str(files_3.strip())
try: #if the file named the same as the searchterm exists, read its contents
file = open(file_1,"r")
file2 = open(file_2,"r")
file3 = open(file_3,"r")
file_contents = file.readlines()
file_contents2 = file2.readlines()
file_contents3 = file3.readlines()
file = open(file_1,"a") #appends the contents of file 3 and file 2 to file 1
print("im about here")
file.write(file_contents2) #fails exactly here I don't know why
file.write(file_contents3)
file2 = open(file_2,"w+")
file2.write(file_contents)
file3 = open(file_3,"w+")
file3.write(file_contents2)

The reason it fails at the point you mention is that you are trying to write a list into the file (not a string). file2.readlines() returns a list of strings, each being their own line so to fix this change all the readlines to filexxx.read() which returns the whole file contents as a string.
I also recommend making the changes the other answer states to make your code more readable/robust.

You start reading from file_ with file = open(file_1, 'r'), and then open it again in append mode, without closing the first I/O operation - causing a failure when you attempt to write to the find while it's open in read mode.
Change your file reading/writing to utilize the less error-prone with open syntax, as follows:
with open(file_1, 'r') as file_handle:
file_contents = file_handle.read()
with open(file_2, 'r') as file_handle:
file_contents2 = file_handle.read()
with open(file_3, 'r') as file_handle:
file_contents3 = file_handle.read()
with open(file_1, 'a') as file_handle:
file_handle.write(file_contents2)
# etc.
This syntax makes it very evident when a file is no longer open, and in what state it is open in.

Related

Python programm for files

I am trying to make a programm that:
will save in a file named "class.txt" the full names of students of a class (one per line)
Then I have to insert the names:
Karamitsos Giorgos
Patapoukas Dimitris
and then close the file.
Read the file and print only the first names.
Following is my attempt:
f = open('class.txt','w')
l = ['karamitsos giorgos \n', 'patapoukas dimitris \n']
f.writelines(l)
f.close()
f1 = open('class.txt','r')
l2 = str(f1.readlines())
l3 = list(l2.split(" "))
print(l3,'\n')
print(l3[1], l3[4])
f1.close()
A few observations:
The output file should probably be opened using mode 'a', which instead of erasing any old file's contents will instead append new data to the end.
By using a context manager to open the file, e.g. with open('class.txt', 'a') as f:, the file will automatically be closed when the with block is exited.
Method readlines will read the entire file into memory in one shot. What if the file has megabytes of data? You should instead iteratively read the file line by line.
You can use print to add additional names to the file. By default a newline will be appended to the end of whatever you are printing.
with open('class.txt','a') as f:
for name in ('karamitsos giorgos', 'patapoukas dimitris'):
print(name, file=f)
with open('class.txt', 'r') as f:
for name in f:
name_parts = name.strip().split(' ')
print(name_parts[0])
However, you can avoid opening and closing the file twice by opening it once for both appending and reading:
with open('class.txt','a+') as f:
for name in ('karamitsos giorgos', 'patapoukas dimitris'):
print(name, file=f)
# Seek to beginning of the file:
f.seek(0, 0)
for name in f:
name_parts = name.strip().split(' ')
print(name_parts[0])

"Move" some parts of the file to another file

Let say I have a file with 48,222 lines. I then give an index value, let say, 21,000.
Is there any way in Python to "move" the contents of the file starting from index 21,000 such that now I have two files: the original one and the new one. But the original one now is having 21,000 lines and the new one 27,222 lines.
I read this post which uses partition and is quite describing what I want:
with open("inputfile") as f:
contents1, sentinel, contents2 = f.read().partition("Sentinel text\n")
with open("outputfile1", "w") as f:
f.write(contents1)
with open("outputfile2", "w") as f:
f.write(contents2)
Except that (1) it uses "Sentinel Text" as separator, (2) it creates two new files and require me to delete the old file. As of now, the way I do it is like this:
for r in result.keys(): #the filenames are in my dictionary, don't bother that
f = open(r)
lines = f.readlines()
f.close()
with open("outputfile1.txt", "w") as fn:
for line in lines[0:21000]:
#write each line
with open("outputfile2.txt", "w") as fn:
for line in lines[21000:]:
#write each line
Which is quite a manual work. Is there a built-in or more efficient way?
You can also use writelines() and dump the sliced list of lines from 0 to 20999 into one file and another sliced list from 21000 to the end into another file.
with open("inputfile") as f:
content = f.readlines()
content1 = content[:21000]
content2 = content[21000:]
with open("outputfile1.txt", "w") as fn1:
fn1.writelines(content1)
with open('outputfile2.txt','w') as fn2:
fn2.writelines(content2)

Strip file names from files and open recursively? Saving previous strings? - PYTHON

I have a question about reading in a .txt rile and taking the string from inside to be used later on in the code.
If I have a file called 'file0.txt' and it contains:
file1.txt
file2.txt
The rest of the files either contain more string file names or are empty.
How can I save both of these strings for later use. What I attempted to do was:
infile = open(file, 'r')
line = infile.readline()
line.split('\n')
But that returned the following:
['file1.txt', '']
I understand that readline only reads one line, but I thought that by splitting it by the return key it would also grab the next file string.
I am attempting to simulate a file tree or to show which files are connected together, but as it stands now it is only going through the first file string in each .txt file.
Currently my output is:
File 1 crawled.
File 3 crawled.
Dead end reached.
My hope was that instead of just recursivley crawling the first file it would go through the entire web, but that goes back to my issue of not giving the program the second file name in the first place.
I'm not asking for a specific answer, just a push in the right direction on how to better handle the strings from the files and be able to store both of them instead of 1.
My current code is pretty ugly, but hopefully it gets the idea across, I will just post it for reference to what I'm trying to accomplish.
def crawl(file):
infile = open(file, 'r')
line = infile.readline()
print(line.split('\n'))
if 'file1.txt' in line:
print('File 1 crawled.')
return crawl('file1.txt')
if 'file2.txt' in line:
print('File 2 crawled.')
return crawl('file2.txt')
if 'file3.txt' in line:
print('File 3 crawled.')
return crawl('file3.txt')
if 'file4.txt' in line:
print('File 4 crawled.')
return crawl('file4.txt')
if 'file5.txt' in line:
print('File 5 crawled.')
return crawl('file5.txt')
#etc...etc...
else:
print('Dead end reached.')
Outside the function:
file = 'file0.txt'
crawl(file)
Using read() or readlines() will help. e.g.
infile = open(file, 'r')
lines = infile.readlines()
print list(lines)
gives
['file1.txt\n', 'file2.txt\n']
or
infile = open(file, 'r')
lines = infile.read()
print list(lines.split('\n'))
gives
['file1.txt', 'file2.txt']
Readline only gets one line from the file so it has a newline at the end. What you want is file.read() which will give you the whole file as a single string. Split that using newline and you should have what you need. Also remember that you need to save the list of lines as a new variable i.e. assign to your line.split('\n') action. You could also just use readlines which will get a list of lines from the file.
change readline to readlines. and no need to split(\n), its already a list.
here is a tutorial you should read
I prepared file0.txt with two files in it, file1.txt, with one file in it, plus file2.txt and file3.txt, which contained no data. Note, this won't extract values already in the list
def get_files(current_file, files=[]):
# Initialize file list with previous values, or intial value
new_files = []
if not files:
new_files = [current_file]
else:
new_files = files
# Read files not already in list, to the list
with open(current_file, "r") as f_in:
for new_file in f_in.read().splitlines():
if new_file not in new_files:
new_files.append(new_file.strip())
# Do we need to recurse?
cur_file_index = new_files.index(current_file)
if cur_file_index < len(new_files) - 1:
next_file = new_files[cur_file_index + 1]
# Recurse
get_files(next_file, new_files)
# We're done
return new_files
initial_file = "file0.txt"
files = get_files(initial_file)
print(files)
Returns: ['file0.txt', 'file1.txt', 'file2.txt', 'file3.txt']
file0.txt
file1.txt
file2.txt
file1.txt
file3.txt
file2.txt and file3.txt were blank
Edits: Added .strip() for safety, and added the contents of the data files so this can be replicated.

I need to open and rewrite a line in a file in Python [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Search and replace a line in a file in Python
How do I modify a text file in Python?
I have an input file that I need to rewrite with the different files needed to be modified before running a program. I have tried a variety of the solutions on here but none of them seem to work. I end up just overwriting my file with a blank file
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()
Or with that code for instance the name I am changing is different each time I run the program so I need to replace the entire line not just one keyword
A simple way may be to read the text into a string, then concatenate the string with the text you want to write:
infile = open('hey.txt','r+')
content = infile.read()
text = ['foo','bar']
for item in text:
content +=item #adds 'foo' on first iteration, 'bar' on second
infile.write(content)
infile.close()
or to change a particular key word:
infile = open('hey.txt','r+')
content = infile.read()
table = str.maketrans('foo','bar')
content = content.translate(table) #replaces 'foo' with 'bar'
infile.write(content)
infile.close()
or to change by line, you can use readlines and refer to each line as the index of a list:
infile = open('hey.txt','r+')
content = infile.readlines() #reads line by line and out puts a list of each line
content[1] = 'This is a new line\n' #replaces content of the 2nd line (index 1)
infile.write(content)
infile.close()
Maybe not a particularly elegant way to solve the problem, but it could be wrapped up in a function and the 'text' variable could be a number of data types like a dictionary, list, etc. There are also a number of ways to replace each line in a file, it just depends on what the criteria are for changing the line (are you searching for a character or word in the line? Are you just looking to replace a line based on where it is in the file?)--so those are also some things to consider.
Edit: Added quotes to third code sample
Though ugly this solution ends up working
infile = open('file.txt', 'r+')
content = infile.readlines() #reads line by line and out puts a list of each line
content[1] = "foo \n" #replaces content of the 2nd line (index 1)
infile.close
infile = open('file.txt', 'w') #clears content of file.
infile.close
infile = open('file.txt', 'r+')
for item in content: #rewrites file content from list
infile.write("%s" % item)
infile.close()
Thanks for all the help!!

How to add a list into a file .txt

hi i was suppose to add a customer name to a customer.txt file
[1, “Amin Milani Fard”, “Columbia College”, 778]
[2, “Ali”, “Douiglas College”, 77238]
def addingcustomer(file_name,new_name):
f=open(file_name,'w')
for line in f:
if new_name==line:
return ("already existed")
elif new_name!=line:
f.write(str(new_name)+"\n")
return ("succesfully added")
it gives me this error:
Traceback (most recent call last):
File "C:\Users\Yuvinng\Desktop\Customer assignment 1\Customer assignment 2", line 77, in <module>
function(c)
File "C:\Users\Yuvinng\Desktop\Customer assignment 1\Customer assignment 2", line 26, in function
print (addingcustomer("customerlist.txt",x))
File "C:\Users\Yuvinng\Desktop\Customer assignment 1\Customer assignment 2", line 60, in addingcustomer
for line in f:
io.UnsupportedOperation: not readable
You probably want to close the file too, after you are done.
f.close()
You are opening the file with w, meaning you ask for write only permissions. Then you try to loop through all lines in the file, which is clearly a read operation. IIRC you should open the file with r+, w+ or a+, depending on what behaviour you want (read here for a description). Furthermore as mentionened by mh512 it is generally a good idea to close your file with f.close() when you're done with it.
However you might also want to rethink your algorithm.
for line in f:
if new_name==line:
return ("already existed")
elif new_name!=line:
f.write(str(new_name)+"\n")
return ("succesfully added")
For every line it processes, this will either return "already existed" if it equals the new name or write the new name to the file and return. Therefore this loop will always return after the first line. Furthermore even if the name already exists at a later point, if it isn't in the first line, it will be written to the file again. Since this is homework I won't give you the complete solution, but as a hint you might want to loop through all lines, before you decide what to do.
Here are a couple of things that might have caused the error:
You started by: "i was suppose to add a customer name to a customer.txt file" but the stack trace you posted says that the file you are trying to read is "customerlist.txt".
You are using the file_open function with 'w' for write privilege. try using 'r' or 'wr'.
E.
Probably not a direct answer to your specific question, but it solves your problem as a sideeffect.
I assume that every line in your code is a python list of the form
line = [id, fullname, establishment, some_integer]
and you (or someone else) stored it just by writing it to a line into the file with name file_name. That's not pythonic at all. You should use a standard format like CSV (Comma-Separated-Value) for the file (which python supports in its librarys with the CSV-module). As delimitter you can chose a comma, a semi-colon or what ever you want. Let's assume you chose a semi-colon as delimitter. Than the file would look like this:
id; name; establishment; some_other_id
"1"; "Amin Milani Fard"; "Columbia College"; "778"
"2", "Ali"; "Douiglas College"; "77238"
etc.
Assuming a list
mylist = ["1"; "Amin Milani Fard"; "Columbia College"; "778"]
you would need a CSV writer two write to this list:
import csv
wFile = open(file_name, 'w')
csvWriter = csv.writer(wFile, delimiter=';')
csvWriter.writerow(mylist) # write list to csv file
rFile.close()
if you want to read the list again you do:
rFile = open(file_name, 'r')
csvReader = csv.reader(rFile, delimiter=';')
for row in csvReader: # step throug rows. Each row is a list.
print ','.join(row)
rFile.close()
I don't this is a big effort for you but I suggest the following, if you want to clean up the files and your code a little bit: Turn the file into a csv file by reading all the lines into a list. turning every list into a valid python list and then write those lists with csvWriter to your file again which will then be a valid csv file. Then use csvreader and csvWriter to add lines to your file if they do not exist.
In your case (assuming the visible formatting is consistent) I would do:
import csv
old_name = 'customer.txt'
new_name = 'customer.csv'
rFile = open(old_name, 'r')
wfile = open(new_name, w)
csvWriter = csv.writer(wFile, delimiter=';')
for line in rFile:
line = line.strip()[1:-1] # strip braces "[" and "]" and newline "\n"
mylist = line.split(', ') # split the line by ', '
csvWriter.writerwo(mylist)
rFile.close()
wFile.close()
You will have a csv file afterwards. No you can use the csvreaders and writers as described.
Edit:
Perhaps the following code snippets helps you to understand what I meant above. csv readers and writers are really not that complicated. See
import csv
# Creating a customer file with some entrys to start with.
wFile = open('test.csv', 'w') # 'w' means crete fresh file
csvWriter = csv.writer(wFile, quoting=csv.QUOTE_MINIMAL)
csvWriter.writerow(['1', 'old', '2', 'customer'])
csvWriter.writerow(['1', 'an other old', '2', 'customer'])
wFile.close() # Don't forget to close the file
new_customers = [ # List of new customers to add if not exist.
['1', 'old', '2', 'customer'], # will not be added.
['4', 'new', '2', 'customer'] # will be added.
]
# First we wont to eliminate existent customers from list `new_customers`
rFile = open('test.csv', 'r') # 'r' means read file
csvReader = csv.reader(rFile)
print new_customers
for row in csvReader:
print row
if row in new_customers:
new_customers.remove(row) # remove customer if exists
rFile.close() # Don't forget to close the file
if new_customers: # there are new customers left in new_customers
wFile = open('test.csv', 'a') # 'a' means append to existing file
csvWriter = csv.writer(wFile, quoting=csv.QUOTE_MINIMAL)
for customer in new_customers:
csvWriter.writerow(customer) # add them to the file.
wFile.close()

Categories

Resources