The output from my print statements outputs the correct lines of data, the output file however only contains the last lines for the 3 if statements. I have tried varying the identation but this seems to only affect the code negatively.
import sys
import tokenize
file = []
f = open('Database.txt') # Opening File
for line in f:
file.append(line) # Reading in File
f.close() # Closing File
f = open('output.txt', 'w')
for line in file: # Printing out File
#print line
tokens = line.split() # splits lines along white-space (tokenise)
#print tokens
desired = '{0:<5}'.format(tokens[0])
#print desired
lined = line.split('|') # lhs is original line
if 'Not present in Line' in line:
line1 = desired + ':' + lined[1]
#print line1
if 'Not present in TV' in line:
#print line
line2 = desired + ' : ' + ' sticking ' + ' Returning ' + '\n'
#print line2
if 'Not present in Line' not in line and 'Not present in TV' not in line:
#print line
line3 = desired + ':' + lined[1]
#print line3
f.write(line1 + line2 + line3)
f.close()
You need to indent the line
f.write(line1 + line2 + line3)
to the same level as the if statements before. Currently, it's outside the for loop and is therefore executed only after that loop has ended.
Also, you may want to add a newline character after each line:
f.write(line1 + line2 + line3 + "\n")
As Jon Clements has noted correctly, you need to think about what should happen if not all three if conditions are met - in that case, lineN variables may be undefined or may still be defined with the value from the previous iteration. In fact, it's impossible for all three conditions to be met at the same time, so you'll always encounter a NameError during the very first iteration.
Only you can decide if it makes sense to set them to a default value at the start of the for loop or to do something else.
Related
I have a text file with random letters,numbers and characters in it. I have to remove the special characters and only end up with alphanumeric ones, while printing the process.
Text file is like this:
fkdjks97#!%&jd
28e8uw99...
and so on
For some reason it's printing:
Line read' ,,s.8,ymsw5w-86
'
' ,,s.8,ymsw5w-86
'->' <filter object at 0x0000020406BC8550> '
These should go on only 2 lines, instead of 4. Like this:
Line read' ,,s.8,ymsw5w-86'
' ,,s.8,ymsw5w-86' -> 's8ymsw5w86'
My attempt:
file1 = open(textfile1,"r")
while True:
line = file1.readline()
line2 = filter(str.isalnum,line)
print("Line read'", str(line), "'")
print("'", str(line), "'->'", line2, "'")
if len(line) == 0:
break
filter() is an iterator object; you'll need to actually iterate over it to pull out the results.
In this case, you want a string back, so you could use str.join() to do the iteration and put everything back into a single string:
line2 = ''.join(filter(str.isalnum, line))
Note that you shouldn't really need to use a while True loop with file1.readline() calls. You can use a for loop directly over the file to get the lines by replacing the while True, line = file1.readline() and if len(line) == 0: break lines with:
for line in file1:
# ...
You might be looking for a regex solution:
import re
rx = re.compile(r'[^A-Za-z]+')
# some sample line
line = 'fkdjks97#!%&jd'
# and then later on
line = rx.sub('', line)
print(line)
Which yields
# fkdjksjd
Putting this in a with... construct, you might be using
with open(textfile1, "r") as fp:
line = rx.sub('', fp.readline())
print(line)
This script is meant to read through a file and take in the number (numA) and the text next to it (sourceA). It then uses this and compares it to every other line in the file. If a match in "nums" is found but not in sources, it writes the num to a file along with the sources it appears in.
with open(sortedNums, "r")as sor:
for line in sor:
NumsA, sourceA = line.split('####')
for line in sor:
if '####' in line:
NumsB, sourceB = line.split('####')
if (NumsA == NumsB) & (sourceA != sourceB):
print("Found reused Nums")
with open(reusedNums, 'a')as reused:
reused.write(NumsA + ' ' + sourceA + ' ' + sourceB)
print ("setA: " + NumsA + ' ' + sourceA)
print ("setB: " + NumsB + ' ' + sourceB)
Most of this is working except that it does the full inner loop but only the first iteration of the outer loop
You are trying to read twice from the same file. Files use a current position to determine what to read next, and iterating over the remaining lines in the inner loop, you moved that position all the way to the end.
You could 'fix' that by seeking back to the start of the file with:
sor.seek(0)
However, looping over the whole file for every line in that file is really inefficient. Use a dictionary to track if you have seen the same information on a previous line:
with open(sortedNums, "r")as sor, \
open(reusedNums, 'a') as reused:
seen = {}
for line in sor:
if not '####' in line:
continue
nums, source = line.rstrip().split('####')
if nums in seen and seen[nums] != source:
print("Found reused Nums")
reused.write('{} {} {}\n'.format(nums, source, seen[nums]))
seen[nums] = source
By storing data in a dictionary, you only have to loop over the file once.
Here is the part of my program which firstly reads a file, checking if the "name" which the user would give is in the file, if it is, then it would add onto the line, but if it isn't then it would start a new line.
r = open("Class%s.txt"%(group),"r")
lines = r.readlines()
r.close()
for i, line in enumerate(lines):
if name in line:
lines[i] = line.strip() + "\t" + str(score) + "\n"
break
else:
lines.append("\n" + name + "\t" + str(score))
w = open("Class%s.txt"%(group),"w")
w.writelines(lines)
w.close()
The problem I have with this program is that if a user named "Alexander" uses the program before a user named "Alex" does so, the program would write "Alex"'s score on the same line as "Alexander"'s as it searches each line for the characters "Alex" and not if it is the EXACT match. Thanks for any help given!
I presume each line looks like
Alexander 25 31 19 16
I suggest comparing like
if name.lower() == line.split(None, 1)[0].lower():
(compare against the line's first word, and ignore capitalization).
Just change
if name in line:
with
if name in line.strip():
This way you'll look into a list of words, not a list of characters. And you'll match complete words.
I am reading a text file and searching data line by line, based on some condition, changing some values in the line and writing it back into another file. The new file should not contain the old Line. I have tried the following, but it did not work. I think I am missing a very basic thing.
Solution: In C++ we can increment line but in Python I am not sure how to achieve this. So as of now, I am writing old line than new line. But in the new file, I want only the new line.
Example:
M0 38 A 19 40 DATA2 L=4e-08 W=3e-07 nf=1 m=1 $X=170 $Y=140 $D=8
M0 VBN A 19 40 TEMP2 L=4e-08 W=3e-07 nf=1 m=1 $X=170 $Y=140 $D=8
The code which i tried is the following:
def parsefile():
fp = open("File1", "rb+")
update_file = "File1" + "_update"
fp_latest = open(update_file, "wb+")
for line in fp:
if line.find("DATA1") == -1:
fp_latest.write(line)
if line.find("DATA1") != -1:
line = line.split()
pin_name = find_pin_order(line[1])
update_line = "DATA " + line[1] + " " + pin_name
fp_latest.write(update_line)
line = ''.join(line)
if line.find("DATA2") != -1:
line_data = line.split()
line_data[1] = "TEMP2"
line_data =' '.join(line_data)
fp_latest.write(line_data)
if line.find("DATA3") != -1:
line_data = line.split()
line_data[1] = "TEMP3"
line_data =' '.join(line_data)
fp_latest.write(line_data)
fp_latest.close()
fp.close()
The main problem with your current code is that your first if block, which checks for "DATA1" and writes the line out if it is not found runs when "DATA2" or "DATA3" is present. Since those have their own blocks, the line ends up being duplicated in two different forms.
Here's a minimal modification of your loop that should work:
for line in fp:
if line.find("DATA1") != -1:
data = line.split()
pin_name = find_pin_order(data[1])
line = "DATA " + data[1] + " " + pin_name
if line.find("DATA2") != -1:
data = line.split()
data[1] = "TEMP2"
line =' '.join(data)
if line.find("DATA3") != -1:
data = line.split()
data[1] = "TEMP3"
line =' '.join(data)
fp_latest.write(line)
This ensures that only one line is written because there's only a single write() call in the code. The special cases simply modify the line that is to be written. I'm not sure I understand the modifications you want to have done in those cases, so there may be more bugs there.
One thing that might help would be to make the second and third if statements into elif statements instead. This would ensure that only one of them would be run (though if you know your file will never have multiple DATA entries on a single line, this may not be necessary).
If you want to write a new line in a file replacing the old content that has been readed last time, you can use the file.seek() method for moving arround the file, there is an example.
with open("myFile.txt", "r+") as f:
offset = 0
lines = f.readlines()
for oldLine in lines:
... calculate the new line value ...
f.seek(offset)
f.write(newLine)
offset += len(newLine)
f.seek(offset)
if data.find('!masters') != -1:
f = open('masters.txt')
lines = f.readline()
for line in lines:
print lines
sck.send('PRIVMSG ' + chan + " " + str(lines) + '\r\n')
f.close()
masters.txt has a list of nicknames, how can I print every line from the file at once?. The code I have only prints the first nickname. Your help will be appreciate it. Thanks.
Firstly, as #l33tnerd said, f.close should be outside the for loop.
Secondly, you are only calling readline once, before the loop. That only reads the first line. The trick is that in Python, files act as iterators, so you can iterate over the file without having to call any methods on it, and that will give you one line per iteration:
if data.find('!masters') != -1:
f = open('masters.txt')
for line in f:
print line,
sck.send('PRIVMSG ' + chan + " " + line)
f.close()
Finally, you were referring to the variable lines inside the loop; I assume you meant to refer to line.
Edit: Oh and you need to indent the contents of the if statement.
You probably want something like:
if data.find('!masters') != -1:
f = open('masters.txt')
lines = f.read().splitlines()
f.close()
for line in lines:
print line
sck.send('PRIVMSG ' + chan + " " + str(line) + '\r\n')
Don't close it every iteration of the loop and print line instead of lines. Also use readlines to get all the lines.
EDIT removed my other answer - the other one in this discussion is a better alternative than what I had, so there's no reason to copy it.
Also stripped off the \n with read().splitlines()
You could try this. It doesn't read all of f into memory at once (using the file object's iterator) and it closes the file when the code leaves the with block.
if data.find('!masters') != -1:
with open('masters.txt', 'r') as f:
for line in f:
print line
sck.send('PRIVMSG ' + chan + " " + line + '\r\n')
If you're using an older version of python (pre 2.6) you'll have to have
from __future__ import with_statement
Loop through the file.
f = open("masters.txt")
lines = f.readlines()
for line in lines:
print line
Did you try
for line in open("masters", "r").readlines(): print line
?
readline()
only reads "a line", on the other hand
readlines()
reads whole lines and gives you a list of all lines.