I've looked at loads of threads on this but cant find the right answer:
I'm a bit new to python. Im opening a file in python, inserting one line before the beginning line and one before the last line and then reconstructing all the lines into a string variable at the end.
Heres the function Im trying to run on the opened file. This changes all lines where mode="0" to mode="1" or vice versa.
def Modes(file, mode):
endstring = ''
if(mode == 1):
mode0 = 'mode="0"'
mode1 = 'mode="1"'
else:
mode0 = 'mode="1"'
mode1 = 'mode="0"'
for line in iter(file):
if 'Modes' in line:
line = line.replace(mode0,mode1)
endstring += line
return endstring
So I try the following:
mode = 1
input_file = open("c:\myfile.txt")
input_file.readlines()
lengthlines = len(input_file)
#insert line at position 1
input_file.insert(1,'<VARIABLE name="init1" />')
#insert line at last line position - 1
input_file.insert(lengthlines,'<VARIABLE name="init2" />')
#join the lines back up again
input_file = "".join(input_file)
#run the modes function - to replace all occurrences of mode=x
finalfile = Modes(input_file,mode)
print finalfile
And then Im getting the error, "object of type file, has no "len()"" and general object/list errors.
It seems Im getting objects/lists etc mixed up but im not sure where - would be grateful for any assistance - cheers
input_file.readlines() returns the content but does not assign it to input_file.
You'll have to assign the return value of the call to a variable, like so:
file_content = input_file.readlines()
and then pass that to len()
lengthlines = len(file_content)
EDIT: solving the issue with len() leads to further exceptions.
This should roughly do what you want:
mode = 1
with open("c:\myfile.txt") as input_file:
file_content = list(input_file.readlines())
file_content.insert(0,'<VARIABLE name="init1" />')
file_content.append('<VARIABLE name="init2" />')
finalfile = Modes(file_content,mode)
print finalfile
You might have to alter your string concatenation in the function if you want to stick with several lines.
endstring += line + '\n'
return endstring.rstrip('\n')
This does not yet write the new content back to the file though.
EDIT2: And it is always good practice to close the file when you are done with it, therefore I updated the above to use a context manager that takes care of this. You could also explicitly call input_file.close() after you are finished.
Related
I am new here and new to Programming too.
I am reading Jamie Chan's Learn Python in One Day and am currently at the Practical Project section. I am trying to make python read a line from a txt file. The txt file contains a name and a number seperated by a comma,
This is the text file
Benny, 102
Ann, 100
Carol, 214
Darren, 129
I succeded in making it read the first line but the trying to print the second line by calling on the name there keeps returning a nill. When I switch the lines, the same thing occurs, it reads the name in the first line but returns nill on the name in the second file.
This is the function I tried to use to read the texts:
def getUserPoint(userName):
f = open('userScores.txt', 'r')
for line in f:
result = line.splitlines()
if userName in line:
return result
else:
return "nill"
f.close()
s = getUserPoint(input('Ann'))
print(s)
And this is the result:
nill
and this is the instructions:
Each line records the information of one user. The first value is the user’s username and the second is the user’s score.
Next, the function reads the file line by line using a for loop. Each line is then split using the split() function
Let’s store the results of the split() function in the list content.
Next, the function checks if any of the lines has the same username as the value that is passed in as the parameter. If there is, the function closes the file and returns the score beside that username. If there isn’t, the function closes the file and returns the string ‘-1’
Am terribly sorry for the long winded post.
you can use :
def getUserPoint(userName):
f = open('userScores.txt', 'r')
for line in f.readlines():
result = line.splitlines()
if userName in line:
f.close()
return result
f.close()
return "nill"
s = getUserPoint(input('Ann'))
print(s)
One problem is that you have an else statement that is matched and will immediately end the function and loop
You need to return the default result after you've looked at all lines
def getUserPoint(userName):
with open('userScores.txt') as f:
for line in f:
if userName == line.rstrip().split(',')[0]:
return line
return "nill"
Then, as shown, you either want to split the comma and check the first column, or userName in line . Otherwise, you are checking
'Ann' in ["Ann, 100", ""]
since splitlines() will split at the newline character at the end, which returns False
See below
The code takes care of closing the file.
It will return None if no match found, else 'user point' is returned
def get_user_point(user_name):
with open('userScores.txt', 'r') as f:
lines = [l.strip() for l in f]
for line in lines:
parts = line.split(',')
if user_name == parts[0]:
return parts[1]
Thanks everyone for the help...
This code by OneCricketeer worked:
def getUserPoint(userName):
with open('userScores.txt') as f:
for line in f:
if userName == line.split(',')[0]:
return line
return "nill"
Since am new to Python and programming in General, I will probably be asking a lot more questions.
Thanks for the help everyone.
I have the following problem. I am supposed to open a CSV file (its an excel table) and read it without using any library.
I tried already a lot and have now the first row in a tuple and this in a list. But only the first line. The header. But no other row.
This is what I have so far.
with open(path, 'r+') as file:
results=[]
text = file.readline()
while text != '':
for line in text.split('\n'):
a=line.split(',')
b=tuple(a)
results.append(b)
return results
The output should: be every line in a tuple and all the tuples in a list.
My question is now, how can I read the other lines in python?
I am really sorry, I am new to programming all together and so I have a real hard time finding my mistake.
Thank you very much in advance for helping me out!
This problem was many times on Stackoverflow so you should find working code.
But much better is to use module csv for this.
You have wrong indentation and you use return results after reading first line so it exits function and it never try read other lines.
But after changing this there are still other problems so it still will not read next lines.
You use readline() so you read only first line and your loop will works all time with the same line - and maybe it will never ends because you never set text = ''
You should use read() to get all text which later you split to lines using split("\n") or you could use readlines() to get all lines as list and then you don't need split(). OR you can use for line in file: In all situations you don't need while
def read_csv(path):
with open(path, 'r+') as file:
results = []
text = file.read()
for line in text.split('\n'):
items = line.split(',')
results.append(tuple(items))
# after for-loop
return results
def read_csv(path):
with open(path, 'r+') as file:
results = []
lines = file.readlines()
for line in lines:
line = line.rstrip('\n') # remove `\n` at the end of line
items = line.split(',')
results.append(tuple(items))
# after for-loop
return results
def read_csv(path):
with open(path, 'r+') as file:
results = []
for line in file:
line = line.rstrip('\n') # remove `\n` at the end of line
items = line.split(',')
results.append(tuple(items))
# after for-loop
return results
All this version will not work correctly if you will '\n' or , inside item which shouldn't be treated as end of row or as separtor between items. These items will be in " " which also can make problem to remove them. All these problem you can resolve using standard module csv.
Your code is pretty well and you are near goal:
with open(path, 'r+') as file:
results=[]
text = file.read()
#while text != '':
for line in text.split('\n'):
a=line.split(',')
b=tuple(a)
results.append(b)
return results
Your Code:
with open(path, 'r+') as file:
results=[]
text = file.readline()
while text != '':
for line in text.split('\n'):
a=line.split(',')
b=tuple(a)
results.append(b)
return results
So enjoy learning :)
One caveat is that the csv may not end with a blank line as this would result in an ugly tuple at the end of the list like ('',) (Which looks like a smiley)
To prevent this you have to check for empty lines: if line != '': after the for will do the trick.
I am new to python, am doing a small assignment, and have hit a bit of a snag. I would like to know how to append to the bottom empty line of a file that I have.
The code already prints out what is in the '.txt' and 'cnt' comes out as the next line with no text in it.
#Open the desired file
f = open("Testing.txt", "r")
#Read out lines of the file and number them
line = f.readline()
cnt = 1
while line:
print("Line {}: {}".format(cnt, line.strip()))
line = f.readline()
cnt += 1
print("Line {}: {}".format(cnt, newline))
f.close()
#Append new line to bottom of file
f = open("Computers.cfg", "a")
f.writelines(newline)[cnt]
f.close()
If the file reads something like
Hello
I am
here
I want to add "now" to the bottom line, so that it reads
Hello
I am
here
now
Am I going about this properly or is there a better or cleaner way to do this?
This is my solution, I've simplified things a fair bit. See if this works for you.
#Open the desired file
f = open("Testing.txt", "r")
text = f.read()
if text[-1] != '\n':
newline = '\n'+newline
f.close()
#Append new line to bottom of file
n = open("Computers.cfg", "w")
n.write(text+newline)
n.close()
“TypeError: 'NoneType' object is not subscriptable” is one of the Python errors does not provide a clear answer for new developers.
What this means is that you are trying to use the subscript (or indexing) operator [] on an object that does not support this operation.
The reason it is referring to NoneType is that the response from File.writelines() is None.
Putting all of this together you are attempting to index into None on the line f.writelines(newline)[cnt].
Changing this line to f.write("\nnow") would resolve the issue ("\n" is the shorthard for newline).
Newbie here. Ultimate mission is to learn how to take two big yaml files and split them into several hundred small files. I haven't yet figured out how to use the ID # as the filename, so one thing at a time.
First: split the big files into many. Here's a tiny bit of my test data file test-file.yml. Each post has a - delimiter on a line by itself:
-
ID: 627
more_post_meta_data_and_content
-
ID: 628
And here's my code that isn't working. So far I don't see why:
with open('test-file.yml', 'r') as myfile:
start = 0
cntr = 1
holding = ''
for i in myfile.read().split('\n'):
if (i == '-\n'):
if start==1:
with open(str(cntr) + '.md','w') as opfile:
opfile.write(op)
opfile.close()
holding=''
cntr += 1
else:
start=1
else:
if holding =='':
holding = i
else:
holding = holding + '\n' + i
myfile.close()
All hints, suggestions, pointers welcome. Thanks.
Reading the entire file into memory and then splitting the memory regions is very inefficient if the input files are large. Try this instead:
with open('test-file.yml', 'r') as myfile:
opfile = None
cntr = 1
for line in myfile:
if line == '-\n':
if opfile is not None:
opfile.close()
opfile = open('{0}.md'.format(cntr),'w')
cntr += 1
opfile.write(line)
opfile.close()
Notice also, you don't close things you have opened in a with context manager; the very purpose of the context manager is to take care of this for you.
As a newbie myself, at first glance your trying to write an undeclared variable op to your output. You were nearly spot on, just need to iterate through your opfile and write the contents:
with open('test-file.yml', 'r') as myfile:
start = 0
cntr = 1
holding = ''
for i in myfile.read().split('\n'):
if (i == '-\n'):
if start==1:
with open(str(cntr) + '.md','w') as opfile:
for line in opfile:
op = line
opfile.write(op)
opfile.close()
holding=''
cntr += 1
else:
start=1
else:
if holding =='':
holding = i
else:
holding = holding + '\n' + i
myfile.close()
Hope this helps!
When you are working in a with context on an open file, the with will automatically take care of closing it for you when you exit this block. So you don't need file.close() anywhere.
There is a function called readlines that outputs a generator that reads a line from an open file one line at a time. That will work much more efficiently than read() followed by a split(). Think about it. You are loading a massive file in memory, and then asking CPU to split that ginormous text by \n character. Not very efficient.
You wrote opfile.write(op). Where is this op defined? Don't you want to write the content in holding that you've defined?
Try the following.
with open('test.data', 'r') as myfile:
counter = 1
content = ""
start = True
for line in myfile.readlines():
if line == "-\n" and not start:
with open(str(counter) + '.md', 'w') as opfile:
opfile.write(content)
content = ""
counter += 1
else:
if not start:
content += line
start = False
# write the last file if test-file.yml doesn't end with a dash
if content != "":
with open(str(counter) + '.md', 'w') as opfile:
opfile.write(content)
I have a problem reading characters from a file. I have a file called fst.fasta and I want to know the number of occurrences of the letters A and T.
This is the first code sample :
f = open("fst.fasta","r")
a = f.read().count("A")
t = f.read().count("T")
print "nbr de A : ", a
print "nbr de T : ", t
The result:
nbr of A : 255
nbr of T : 0
Even if there are Ts i get always 0
But after that, I tried this :
f = open("fst.fasta","r")
a = f.read().count("A")
f = open("fst.fasta","r")
t = f.read().count("T")
print "nbr de A : ", a
print "nbr de T : ", t
This worked! Is there any other way to avoid repeating f = open("fst.fasta","r") ?
You're dealing with the fact that read() has a side effect (to use the term really loosely): it reads through the file and as it does so sets a pointer to where it is in that file. When it returns you can expect that pointer to be set to the last position. Therefore, executing read() again starts from that position and doesn't give you anything back. This is what you want:
f = open("fst.fasta","r")
contents = f.read()
a = contents.count("A")
t = contents.count("T")
The documentation also indicates other ways you can use read:
next_value = f.read(1)
if next_value == "":
# We have reached the end of the file
What has happened in the code above is that, instead of getting all the characters in the file, the file handler has only returned 1 character. You could replace 1 with any number, or even a variable to get a certain chunk of the file. The file handler remembers where the above-mentioned pointer is, and you can pick up where you left off. (Note that this is a really good idea for very large files, where reading it all into memory is prohibitive.)
Only once you call f.close() does the file handler 'forget' where it is - but it also forgets the file, and you'd have to open() it again to start from the beginning.
There are other functions provided (such as seek() and readline()) that will let you move around a file using different semantics. f.tell() will tell you where the pointer is in the file currently.
Each time you call f.read(), it consumes the entire remaining contents of the file and returns it. You then use that data only to count the as, and then attempt to read the data thats already been used. There are two solutions"
Option 1: Use f.seek(0)
a = f.read().count("A")
f.seek(0)
t = f.read().count("T")
The f.seek call sets the psoition of the file back to the beginning.
Option 2. Store the result of f.read():
data = f.read()
a = data.count("A")
t = data.count("T")
f.seek(0) before the second f.read() will reset the file pointer to the beginning of the file. Or more sanely, save the result of f.read() to a variable, and you can then call .count on that variable to your heart's content without rereading the file pointlessly.
Try the with construct:
with open("fst.fasta","r") as f:
file_as_string = f.read()
a = file_as_string.count("A")
t = file_as_string.count("T")
This keeps the file open until you exit the block.
Read it into a string:
f = open ("fst.fasta")
allLines = f.readlines()
f.close()
# At this point, you are no longer using the file handler.
for line in allLines:
print (line.count("A"), " ", line.count("T"))