How to flush to a file in python? - python

I have this snippet and a weird thing is going on:
out = open("./out.txt","w+")
for line in open("./int.txt","r").readlines():
for key in dic.keys():
if line.count(key) > 0:
line = re.sub(key,dic[key],line)
print line
out.write(line)
The output to the shell of python is the right one it contains all the lines after the switches according to the dic{} while the out file contains just about half of the lines?

I recommend using the with statement to manage the context of your output file handle so that it is closed at the end of the scope (so that when you view it, it is up-to-date). The for loop does this for you with your input file.
with open("./out.txt", "w+") as out:
for line in open("./int.txt", "r"):
for key in dic.keys():
if key in line:
line = re.sub(key, dic[key], line)
print line,
out.write(line)
A few other minor changes:
.readlines() is not required
if key in line: will stop searching for key in line once it has found the first instance, improving effiency.
print line, will not add another new-line after line.
Also consider whether line = line.replace(key, dic[key]) would suffice, since you're not searching for a regular expression on the line.

files don't always get written to disk straight away, they need flushing
try out.flush() at the end

Related

Unable to read multiline files in python using readline()

The following code is not working properly. It is unable to read multiline files in python using readline().
myobject=open("myfile.txt",'r')
while ((myobject.readline())):
print(myobject.readline())
myobject.close()
It just prints the first line and then newlines. I don't understand why?
It's because readline reads one line at a time, your code will still print a new line because readline keeps trailing newlines.
The way to fix would be to do this:
with open("myfile.txt", 'r') as f:
for line in f:
print(line)
readline() returns the line that it is currently pointing to and moves to the next line. So, the calls to the function in the while condition and in the print statement are not the same. In fact, they are pointing to adjacent lines.
First, store the line in a temporary variable, then check and print.
myobject = open('myfile.txt')
while True:
line = myobject.readline()
if line:
print(line)
else:
break
When you open the file in 'r' mode, the file object returned points at the beginning of the file.
Everytime you call readline, a line is read, and the object now points to the next line in the file
Since your loop condition also reads the file and moves it to the next line, you are getting lines only at even places, like line no 2, 4, 6. Line Numbers, 1, 3, 5, ... will be read by while ((myobject.readline())): and discarded.
A simple solution will be
myobject = open("myfile.txt",'r')
for line in myobject:
print(line, end='')
myobject.close()
OR for your case, when you want to use only readline()
myobject = open("myfile.txt",'r')
while True:
x = myobject.readline()
if len(x) == 0:
break
print(x, end='')
myobject.close()
This code works, because readline behaves in the following way.
According to python documentation, https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects
f.readline() reads a single line from the file; a newline character (\n) is left at the end of the string, and is only omitted on the last line of the file if the file doesn’t end in a newline. This makes the return value unambiguous; if f.readline() returns an empty string, the end of the file has been reached, while a blank line is represented by '\n', a string containing only a single newline.

using readline() and then using it in write() with a message behind it will save to next line

When you readline() from a file and try to write it to another txt file with text behind it the text behind it always goes to the next line, is there any way to not let it go to the next line and just put it behind it?
example code:
file = open('directory/whatever/file.txt', 'r')
file2 = open('directory/whatever/file2.txt', 'a')
line = file.readline()
file2.write(line + 'Thiswillprintonthenextline')
the message behind it will print on the next line
that's what I want to prevent
file2.write(line.rstrip('\n') + 'Thiswillprintonthenextline')
That is because the readline() function creates a string with the newline character at the end.
If you want to print it without changing the lines, simply strip the last character:
file2.write(line.rstrip("\n") + 'Thiswillprintonthenextline')
You could also strip it immediately when reading, so you don't have to do it every time you want to print it...
Just replace the line
line = file.readline()
with the line
line = file.readline().rstrip("\n")
and you're done. ;)
(Thanks to bruno desthuilliers for suggesting rstrip.)

Reading through a .m File and Python keeps reading a character in the .m File as a line?

I am trying to read the text within a .m file in Python and Python keeps reading a single character within the .m file as a line when I use file.readline(). I've also had issues with trying to remove certain parts of the line before adding it to a list.
I've tried adjusting where the readline is on for loops that I have set up since I have to read through multiple files in this program. No matter where I put it, the string always comes out separated by character. I'm new to Python so I'm trying my best to learn what to do.
# Example of what I did
with open('MyFile.m') as f:
for line in f:
text = f.readline()
if text.startswith('%'):
continue
else:
my_string = text.strip("=")
my_list.append(my_string)
This has only partially worked as it will still return parts of lines that I do not want and when trying to format the output by putting spaces between new lines it output like so:
Expected: "The String"
What happened: "T h e S t r i n g"
Without your input file I've had to make some guesses here
Input file:
%
The
%
String
%
Solution:
my_list = []
with open('MyFile.m') as f:
for line in f:
if not line.startswith('%'):
my_list.append(line.strip("=").strip())
print(' '.join(my_list))
The readLine() call was unnecessary as the for loop already gets you the line. The empty if was negated to only catch the part that you cared about. Without your actual input file I can't help with the '=' part. If you have any clarifications I'd be glad to help further.
As suggested by Xander, you shouldn't call readline since the for line in f does that for you.
my_list = []
with open('MyFile.m') as f:
for line in f:
line = line.strip() # lose the \n if you want to
if line.startswith('%'):
continue
else:
my_string = line.strip("=")
my_list.append(my_string)

Add lines to text file after occurence of certain text

I have a text file that I needs to manipulate. I want to add a line after occurence of word "exactarch". Means whenever "exactarch" occurs, I want to add text in the next line.
E.g. If this is the original file content,
[main]
cachedir=/var/cache/yum
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
distroverpkg=redhat-release
tolerant=1
exactarch=1
gpgcheck=1
plugins=1
I want to change it as below:
[main]
cachedir=/var/cache/yum
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
distroverpkg=redhat-release
tolerant=1
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
This is what I tried to do:
with open('file1.txt') as f:
for line in input_data:
if line.strip() == 'exactarch':
f.write('obsoletes=1')
Obviously this is not working as I can't figure out how can I count and write to this line.
You ask for a Python solution. But tasks like this are made to be solved using simpler tools.
If you are using a system that has sed, you can do this in a simle one-liner:
$ sed '/exactarch/aobsoletes=1' < in.txt
What does this mean?
sed: the executable
/exactarch/: matches all lines that contain exactarch
a: after the current line, append a new line with the following text
obsoletes=1: the text to append in a new line
Output:
[main]
cachedir=/var/cache/yum
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
distroverpkg=redhat-release
tolerant=1
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
Edit:
To modify the file in place, use the option -i and the file as an argument:
$ sed -i '/exactarch/aobsoletes=1' in.txt
Simple - read all lines, find correct line and insert desired line after found. Dump result lines to file.
import os
with open('lines.txt') as f:
lines = f.readlines()
lines.insert(lines.index('exactarch=1\n') + 1, 'obsoletes=1\n')
with open('dst.txt', 'w') as f:
for l in lines:
f.write(l)
The past says it's pretty simple - replacing words in files is not a new thing.
If you want to replace a word, you can use the solution implemented there. In your context:
import fileinput
for line in fileinput.input(fileToSearch, inplace=True):
print(line.replace("exactarch", "exactarch\nobsoletes=1"), end='')
I am hesitant using fileinput, b/c if something goes wrong during the 'analysis' phase you are left with a file in whatever conditions it was left before the failure. I would read everything in, and then do full work on it. The code below ensures that:
Your inserted value contains a newline value '\n' if it's not going to be the last item.
Will not add duplicate inserted values by checking the one below it.
Iterates through all values incase multiple "exactarch=1"s were added since the snippet last ran.
Hope this helps, albeit not as stylish as a one/two liner.
with open('test.txt') as f:
data = f.readlines()
insertValue = 'obsoletes=1'
for item in data:
if item.rstrip() == 'exactarch=1': #find it if it's in the middle or the last line (ie. no '\n')
point = data.index(item)
if point+1 == len(data): #Will be inserted as new line since current exactarch=1 is in last position, so you don't want the '\n', right?
data.insert(point+1, instertValue)
else:
if data[point + 1].rstrip() != insertValue: #make sure the value isn't already below exactarch=1
data.insert(point+1, insertValue + '\n')
print('insertValue added below "exactarch=1"')
else:
print('insertValue already exists below exactarch=1')
with open('test.txt','w') as f:
f.writelines(data)

Comparing Two Text Files, Removing the duplicate lines, and Writing results to a new text file

I have two text files (that are not equal in number of lines/size). I would like to compare each line of the shorter text file with every line of the longer text file. As it compares, if there are any duplicate strings, I would like to have those removed. Lastly, I would like write the result to a new text file and print the contents.
Is there a simply script that can do this for me?
Any help would be much appreciated.
The text files are not very large. One has about 10 lines and the other has about 5. The code I have tried (that failed miserably) is below:
for line in file2:
line1 = line
for line in file1:
requested3 = file('request2.txt','a')
if fnmatch.fnmatch(line1,line):
line2 = line.replace(line,"")
requested3.write(line2)
if not fnmatch.fnmatch(line1,line):
requested3.write(line+'\n')
requested3.close()
with open(longfilename) as longfile, open(shortfilename) as shortfile, open(newfilename, 'w') as newfile:
newfile.writelines(line for line in shortfile if line not in set(longfile))
It's as simple as that. This will copy lines from shortfile to newfile, without having to keep them all in memory, if they also exist in longfile.
If you're on Python 2.6 or older, you would need to nest the with statements:
with open(longfilename) as longfile:
with open(shortfilename) as shortfile:
with open(newfilename, 'w') as newfile:
If you're on Python 2.5, you need to either:
from __future__ import with_statement
at the very top of your file, or just use
longfile = open(longfilename)
etc. and close each file yourself.
If you need to manipulate the lines, an explicit for loop is fine, the important part is set(). Looking up an item in a set is fast, looking up a line in a long list is slow.
longlines = set(line.strip_or_whatever() for line in longfile)
for line in shortfile:
if line not in longlines:
newfile.write(line)
Assuming the files are both plain text, each string is on a new line delimited with \n newline characters:
small_file = open('file1.txt','r')
long_file = open('file2.txt','r')
output_file = open('output_file.txt','w')
try:
small_lines = small_file.readlines()
long_lines = long_file.readlines()
small_lines_cleaned = [line.rstrip().lower() for line in small_lines]
long_file_lines = long_file.readlines()
long_lines_cleaned = [line.rstrip().lower() for line in long_lines]
for line in small_lines_cleaned:
if line not in long_lines_cleaned:
output_file.writelines(line + '\n')
finally:
small_file.close()
long_file.close()
output_file.close()
Explanation:
Since you can't get 'with' statements working, we open the files first using regular open functions, then use a try...finally clause to close them at the end of the program.
We take the small file and the long file and first remove any trailing '\n' (newline) characters with .rstrip(), then make all the characters lower-case with .lower(). If you have two sentences identical in every aspect except one has upper case letters and the other doesn't, they wont' match. Forcing them lower case avoids that; if you prefer a case-sensitive compare, remove the .lower() method.
We go line by line in small_lines_cleaned (for line in...) and see if it is in the larger file.
Output each line if it is not in the longer file; we add the '\n' newline character so that each line will appear on a new line, insteadOfOneGiantLongSetOfStrings
I'd use difflib, it makes it easy to do comparisons/diffs. There is a nice tutorial for it here. If you just wanted the lines that were unique to the shorter file:
from difflib import ndiff
short = open('short.txt').readlines()
long = open('long.txt').readlines()
with open('unique.txt', 'w') as f:
f.write(''.join(x[2:] for x in ndiff(short, long) if x.startswith('-')))
Your code as it stands checks each line against the line in the other file. But that's not what you want. For each line in the first file, you need to check whether any line in the other file matches and then print it out if there are no matches.
The following code reads file two and checks it against file one.Anything that's in file one but not in file two will get printed and also written to a new text file.
If you wanted to do the opposite, you'd just get rid of the "not" from if statement below. So it'd print anything that's in file one and in file two.
It works by putting the contents of the shorter file (file two) in a variable and then reading the longer file (file one) line by line. Each line is checked against the variable and then the line is either written or not written to the text file according to it's presence in the variable.
(Remember to remove the stars surrounding the not statement if you wish to use it, or removing the not statement all together if you want it to print the matching words.)
fileOne = open("LONG FILE.ext","r")
fileTwo = open("SHORT FILE.ext","r")
fileThree = open("Results.txt","a+")
contents = fileTwo.read()
numLines = sum(1 for line in fileOne)
for i in range (numLines):
if **not** fileOne.readline(i) in contents:
print (fileOne.readline(i))
fileThree.write (fileOne.readline(i))
fileOne.close()
fileTwo.close()
fileThree.close()

Categories