Copy the last three lines of a text file in python? - python

I'm new to python and the way it handles variables and arrays of variables in lists is quite alien to me. I would normally read a text file into a vector and then copy the last three into a new array/vector by determining the size of the vector and then looping with a for loop a copy function for the last size-three into a new array.
I don't understand how for loops work in python so I can't do that.
so far I have:
#read text file into line list
numberOfLinesInChat = 3
text_file = open("Output.txt", "r")
lines = text_file.readlines()
text_file.close()
writeLines = []
if len(lines) > numberOfLinesInChat:
i = 0
while ((numberOfLinesInChat-i) >= 0):
writeLine[i] = lines[(len(lines)-(numberOfLinesInChat-i))]
i+= 1
#write what people say to text file
text_file = open("Output.txt", "w")
text_file.write(writeLines)
text_file.close()

To get the last three lines of a file efficiently, use deque:
from collections import deque
with open('somefile') as fin:
last3 = deque(fin, 3)
This saves reading the whole file into memory to slice off what you didn't actually want.
To reflect your comment - your complete code would be:
from collections import deque
with open('somefile') as fin, open('outputfile', 'w') as fout:
fout.writelines(deque(fin, 3))

As long as you're ok to hold all of the file lines in memory, you can slice the list of lines to get the last x items. See http://docs.python.org/2/tutorial/introduction.html and search for 'slice notation'.
def get_chat_lines(file_path, num_chat_lines):
with open(file_path) as src:
lines = src.readlines()
return lines[-num_chat_lines:]
>>> lines = get_chat_lines('Output.txt', 3)
>>> print(lines)
... ['line n-3\n', 'line n-2\n', 'line n-1']

First to answer your question, my guress is that you had an index error you should replace the line writeLine[i] with writeLine.append( ). After that, you should also do a loop to write the output :
text_file = open("Output.txt", "w")
for row in writeLine :
text_file.write(row)
text_file.close()
May I suggest a more pythonic way to write this ? It would be as follow :
with open("Input.txt") as f_in, open("Output.txt", "w") as f_out :
for row in f_in.readlines()[-3:] :
f_out.write(row)

A possible solution:
lines = [ l for l in open("Output.txt")]
file = open('Output.txt', 'w')
file.write(lines[-3:0])
file.close()

This might be a little clearer if you do not know python syntax.
lst_lines = lines.split()
This will create a list containing all the lines in the text file.
Then for the last line you can do:
last = lst_lines[-1]
secondLAst = lst_lines[-2]
etc... list and string indexes can be reached from the end with the '-'.
or you can loop through them and print specific ones using:
start = start line, stop = where to end, step = what to increment by.
for i in range(start, stop-1, step):
string = lst_lines[i]
then just write them to a file.

Related

delete all rows up to a specific row

How you can implement deleting lines in a text document up to a certain line?
I find the line number using the code:
#!/usr/bin/env python
lookup = '00:00:00'
filename = "test.txt"
with open(filename) as text_file:
for num, line in enumerate(text_file, 1):
if lookup in line:
print(num)
print(num) outputs me the value of the string, for example 66.
How do I delete all the lines up to 66, i.e. up to the found line by word?
As proposed here with a small modification to your case:
read all lines of the file.
iterate the lines list until you reach the keyword.
write all remaining lines
with open("yourfile.txt", "r") as f:
lines = iter(f.readlines())
with open("yourfile.txt", "w") as f:
for line in lines:
if lookup in line:
f.write(line)
break
for line in lines:
f.write(line)
That's easy.
filename = "test.txt"
lookup = '00:00:00'
with open(filename,'r') as text_file:
lines = text_file.readlines()
res=[]
for i in range(0,len(lines),1):
if lookup in lines[i]:
res=lines[i:]
break
with open(filename,'w') as text_file:
text_file.writelines(res)
Do you know what lines you want to delete?
#!/usr/bin/env python
lookup = '00:00:00'
filename = "test.txt"
with open(filename) as text_file, open('okfile.txt', 'w') as ok:
lines = text_file.readlines()
ok.writelines(lines[4:])
This will delete the first 4 lines and store them in a different document in case you wanna keep the original.
Remember to close the files when you're done with them :)
Providing three alternate solutions. All begin with the same first part - reading:
filename = "test.txt"
lookup = '00:00:00'
with open(filename) as text_file:
lines = text_file.readlines()
The variations for the second parts are:
Using itertools.dropwhile which discards items from the iterator until the predicate (condition) returns False (ie discard while predicate is True). And from that point on, yields all the remaining items without re-checking the predicate:
import itertools
with open(filename, 'w') as text_file:
text_file.writelines(itertools.dropwhile(lambda line: lookup not in line, lines))
Note that it says not in. So all the lines before lookup is found, are discarded.
Bonus: If you wanted to do the opposite - write lines until you find the lookup and then stop, replace itertools.dropwhile with itertools.takewhile.
Using a flag-value (found) to determine when to start writing the file:
with open(filename, 'w') as text_file:
found = False
for line in lines:
if not found and lookup in line: # 2nd expression not checked once `found` is True
found = True # value remains True for all remaining iterations
if found:
text_file.write(line)
Similar to #c yj's answer, with some refinements - use enumerate instead of range, and then use the last index (idx) to write the lines from that point on; with no other intermediate variables needed:
for idx, line in enumerate(lines):
if lookup in line:
break
with open(filename, 'w') as text_file:
text_file.writelines(lines[idx:])

Python3 - list index out of range - extracting data from file

I want to extract data from a file and change the value of an entry with a 'for-loop'.
f = open(r"C:\Users\Measurement\LOGGNSS.txt", "r")
x=0
content = [[],[]]
for line in f:
actualline = line.strip()
content.append(actualline.split(","))
x+=1
f.close
print(x)
for z in range(x):
print(z)
print(content[z][1])
IndexError: list index out of range
Using a real value instead of the variable 'z' works fine. But I need to change all first entries in the whole 2D-Array.
Why it does not work?
Your code has several problems.
First of all, use the with statement to open/close files correctly.
Then, you don't need to use a variable like x to keep track of the number of lines, just use enumerate() instead!
Here is how I would refactor your code to make it slimmer and more readable.
input_file = r"C:\Users\Measurement\LOGGNSS.txt"
content = []
with open(input_file, 'r') as f:
for line in f:
clean_line = line.strip().split(",")
content.append(clean_line)
for z, data in enumerate(content):
print(z,'\n',data)
Note that you could print the content while reading the file in one single loop.
with open(input_file, 'r') as f:
for z, line in enumerate(f):
clean_line = line.strip().split(",")
content.append(clean_line)
print(z,'\n', clean_line)
Finally, if you are dealing with a plain and simple csv file, then use the csv module from the standard library.
import csv
with open(input_file, 'r') as f:
content = csv.reader(f, delimiter=',')
You initialize your content with two empty arrays, so both of these will fail to find the first index ([1]), just initialize it with an empty array
content = []

Read text file to list in python

I want to create a text file which contains positive/negative numbers separated by ','.
i want to read this file and put it in data = []. i have written the code below and i think that it works well.
I want to ask if you guys know a better way to do it or if is it well written
thanks all
#!/usr/bin/python
if __name__ == "__main__":
#create new file
fo = open("foo.txt", "w")
fo.write( "111,-222,-333");
fo.close()
#read the file
fo = open("foo.txt", "r")
tmp= []
data = []
count = 0
tmp = fo.read() #read all the file
for i in range(len(tmp)): #len is 11 in this case
if (tmp[i] != ','):
count+=1
else:
data.append(tmp[i-count : i])
count = 0
data.append(tmp[i+1-count : i+1])#append the last -333
print data
fo.close()
You can use split method with a comma as a separator:
fin = open('foo.txt')
for line in fin:
data.extend(line.split(','))
fin.close()
Instead of looping through, you can just use split:
#!/usr/bin/python
if __name__ == "__main__":
#create new file
fo = open("foo.txt", "w")
fo.write( "111,-222,-333");
fo.close()
#read the file
with open('foo.txt', 'r') as file:
data = [line.split(',') for line in file.readlines()]
print(data)
Note that this gives back a list of lists, with each list being from a separate line. In your example you only have one line. If your files will always only have a single line, you can just take the first element, data[0]
To get the whole file content(numbers positive and negative) into list you can use split and splitlines
file_obj = fo.read()#read your content into string
list_numbers = file_obj.replace('\n',',').split(',')#split on ',' and newline
print list_numbers

generating list by reading from file

i want to generate a list of server addresses and credentials reading from a file, as a single list splitting from newline in file.
file is in this format
login:username
pass:password
destPath:/directory/subdir/
ip:10.95.64.211
ip:10.95.64.215
ip:10.95.64.212
ip:10.95.64.219
ip:10.95.64.213
output i want is in this manner
[['login:username', 'pass:password', 'destPath:/directory/subdirectory', 'ip:10.95.64.211;ip:10.95.64.215;ip:10.95.64.212;ip:10.95.64.219;ip:10.95.64.213']]
i tried this
with open('file') as f:
credentials = [x.strip().split('\n') for x in f.readlines()]
and this returns lists within list
[['login:username'], ['pass:password'], ['destPath:/directory/subdir/'], ['ip:10.95.64.211'], ['ip:10.95.64.215'], ['ip:10.95.64.212'], ['ip:10.95.64.219'], ['ip:10.95.64.213']]
am new to python, how can i split by newline character and create single list. thank you in advance
You could do it like this
with open('servers.dat') as f:
L = [[line.strip() for line in f]]
print(L)
Output
[['login:username', 'pass:password', 'destPath:/directory/subdir/', 'ip:10.95.64.211', 'ip:10.95.64.215', 'ip:10.95.64.212', 'ip:10.95.64.219', 'ip:10.95.64.213']]
Just use a list comprehension to read the lines. You don't need to split on \n as the regular file iterator reads line by line. The double list is a bit unconventional, just remove the outer [] if you decide you don't want it.
I just noticed you wanted the list of ip addresses joined in one string. It's not clear as its off the screen in the question and you make no attempt to do it in your own code.
To do that read the first three lines individually using next then just join up the remaining lines using ; as your delimiter.
def reader(f):
yield next(f)
yield next(f)
yield next(f)
yield ';'.join(ip.strip() for ip in f)
with open('servers.dat') as f:
L2 = [[line.strip() for line in reader(f)]]
For which the output is
[['login:username', 'pass:password', 'destPath:/directory/subdir/', 'ip:10.95.64.211;ip:10.95.64.215;ip:10.95.64.212;ip:10.95.64.219;ip:10.95.64.213']]
It does not match your expected output exactly as there is a typo 'destPath:/directory/subdirectory' instead of 'destPath:/directory/subdir' from the data.
This should work
arr = []
with open('file') as f:
for line in f:
arr.append(line)
return [arr]
You could just treat the file as a list and iterate through it with a for loop:
arr = []
with open('file', 'r') as f:
for line in f:
arr.append(line.strip('\n'))

Making tail function: Reversing lines in a file

I'm trying to define a function that outputs the last n lines in a file. The function below seems to mostly work, aside from the fact that the first two lines in fReverse are being joined and I can't figure out why...
example: (I tried putting these in blockquotes instead of code, but it ruins the line formatting)
f =
Darkly I gaze into the days ahead,
And see her might and granite wonders there,
Beneath the touch of Time’s unerring hand,
Like priceless treasures sinking in the sand.
fReverse =
Like priceless treasures sinking in the sand.Beneath the touch of Time’s unerring hand,
And see her might and granite wonders there,
Darkly I gaze into the days ahead,
Code:
def tail(filename, nlines):
'''Returns a list containing the last n lines of the file.'''
f = open(filename, 'r')
fReverse = open('output.txt', 'w')
fReverse.writelines(reversed(f.readlines()))
fReverse.close()
f.close()
fReverse = open('output.txt', 'r')
listFile = []
for i in range(1,nlines+1):
listFile.append(fReverse.readline(),)
fReverse.close()
return listFile
fname = raw_input('What is the name of the file? ')
lines = int(raw_input('Number of lines to display? '))
print "The last %d lines of the file are: \n%s" % (lines, ''.join(tail(fname, lines)))
Easier to use a deque here:
To reverse the whole file:
from collections import deque
with open('file') as fin:
reversed_lines = deque()
reversed_lines.extendleft(fin)
To display the last n (but iterating through all lines first):
with open('file') as fin:
last4 = deque(fin, 4)
This function can be simplified down quite a bit:
def tail(filename, number_lines):
with open(filename, 'r') as file:
with open('output.txt', 'w') as output:
reversed_lines = file.readlines()[::-1]
output.write('\n'.join([line.strip() for line in reversed_lines]))
return reversed_lines[:number_lines-1]
The issue here is that the last line of your file does not end with a newline character. So f.readlines() will be something like the following (note that the final entry does not have the \n):
['Darkly I gaze into the days ahead,\n',
'And see her might and granite wonders there,\n',
'Beneath the touch of Time’s unerring hand,\n',
'Like priceless treasures sinking in the sand.']
So when you reverse this you end up writing to the file your first "line" doesn't actually write a \n and fReverse.writelines() doesn't add a line ending automatically. To fix this, just check to see if the last line from f.readlines() ends with \n and add it if necessary:
def tail(filename, nlines):
'''Returns a list containing the last n lines of the file.'''
f = open(filename, 'r')
fReverse = open('output.txt', 'w')
lines = f.readlines()
if not lines[-1].endswith('\n'):
lines[-1] += '\n'
fReverse.writelines(reversed(lines))
fReverse.close()
f.close()
fReverse = open('output.txt', 'r')
listFile = []
for i in range(1,nlines+1):
listFile.append(fReverse.readline(),)
fReverse.close()
return listFile
That's because the last line has no \n with it at the end ;P
You can try:
lines = reversed([l.strip()+'\n' for l in f])
fReverse.writelines(lines)

Categories