When you do : f.readlines() you already read all the file so f.tell() will show you that you are in the end of the file, and doing f.next() will result in a StopIteration error.
Alternative of what you want to do is:
filne = "D:/testtube/testdkanimfilternode.txt"
with open(filne, 'r+') as f:
for line in f:
if line.startswith("anim "):
print f.next()
# Or use next(f, '') to return <empty string> instead of raising a
# StopIteration if the last line is also a match.
break
Answer from mouad on Stack OverflowWhen you do : f.readlines() you already read all the file so f.tell() will show you that you are in the end of the file, and doing f.next() will result in a StopIteration error.
Alternative of what you want to do is:
filne = "D:/testtube/testdkanimfilternode.txt"
with open(filne, 'r+') as f:
for line in f:
if line.startswith("anim "):
print f.next()
# Or use next(f, '') to return <empty string> instead of raising a
# StopIteration if the last line is also a match.
break
next() does not work in your case because you first call readlines() which basically sets the file iterator to point to the end of file.
Since you are reading in all the lines anyway you can refer to the next line using an index:
filne = "in"
with open(filne, 'r+') as f:
lines = f.readlines()
for i in range(0, len(lines)):
line = lines[i]
print line
if line[:5] == "anim ":
ne = lines[i + 1] # you may want to check that i < len(lines)
print ' ne ',ne,'\n'
break
your code is handling each line as a term, in the code below f is an iterator so you can use next to move it to the next element:
with open('test.txt') as f:
for line in f:
nextLine = next(f)
if 'A' == line.strip():
print nextLine
If your filesize is small, then you may simply read the file by using readlines() which returns a list of strings each delimited by \n character, and then find the index of the selected word, and the print the item at position + 1 in the given list.
This can be done as:
def searcher():
print("Please enter the term you would like the definition for")
find = input()
with open("glossaryterms.txt", "r") as f:
words = list(map(str.strip, f.readlines()))
try:
print(words[words.index(find) + 1])
except:
print("Sorry the word is not found.")
Videos
Once you found the tag, just break from the loop and start reading names, it will continue reading from the position where you interrupted:
for line in file:
if '[FOR_EACH_NAME]' in line:
break
else:
raise Exception('Did not find names') # could not resist using for-else
for _ in range(5):
line = file.readline()
if 'Name' in line:
print(line)
Are the names in the lines following FOR_EACH_NAME? if so, you can check what to look for in an extra variable:
file=open("file.txt","r")
names = 0
for line in file:
if "[FOR_EACH_NAME]" in line
names = 5
elif names > 0:
if "Name" in line:
print(line)
names -= 1
Just loop over the open file:
infile = open(input,"r")
for line in infile:
line = doSomething(line, next(infile))
Because you now use the file as an iterator, you can call the next() function on the infile variable at any time to retrieve an extra line.
Two extra tips:
Don't call your variable
file; it masks the built-infiletype object in python. I named itinfileinstead.You can use the open file as a context manager with the
withstatement. It'll close the file for you automatically when done:with open(input,"r") as infile: for line in infile: line = doSomething(line, next(infile))
file = open(input,"r").read()
lines = file.read().splitlines()
for i in range(len(lines)):
line = lines[i]
next_line = lines[i+1]
Here's what you are trying to do, and probably could have gotten there with a little debugging.
temp_keywords = ''
mykeywords = ''
with open(input_file, encoding="utf8") as fo:
for line in fo:
if line[:2].isupper():
if line[:2] == 'GJ':
temp_line = line[2:].strip()
next_line = next(fo)
temp_line += next_line.strip()
print (temp_line.split(';'))
The problem here is that calling next(fo) yourself, instead of letting the for loop do its job, means you have to handle all of the for loop's job. So whatever you read into next_line will NOT be processed on the next loop. You will completely miss some lines of the file.
Instead, you always want to let the for loop handle its job.
But what you have here is two different methods of breaking a file up. It's easier to write a record parser which finds full records, and let it read lines from the file as needed. Here is an adaptation of my other answer linked in comments:
def is_new_record(line):
return line[:2].isupper()
def helper(text):
data = []
for line in text.readlines():
if is_new_record(line):
if (data):
yield ''.join(data)
data = [line.strip()]
else:
data.append(line.strip())
if (data):
yield ''.join(data)
# the helper is a generator for multiline records, as one line
input_file = 'data.txt'
with open(input_file) as f:
for record in helper(f):
print (record)
LA English
DT Article
GJ asthma; susceptible genes; natural language processing analysis; networkcentrality analysis
ID LITERATURE-BASED DISCOVERY; CO-WORD ANALYSIS; UNDISCOVERED PUBLICKNOWLEDGE; INFORMATION-RETRIEVAL; FISH-OIL; SCIENTIFIC COLLABORATION;INSULIN-RESISTANCE; COMPLEX NETWORKS; METFORMIN; OBESITY
GJ natural language processing; network analysis
GJ data mining; text mining; learning analytics; deep learning;network centrality analysis
Let's try spliting the problem. There are two main logic processes in your code:
- Extract each non-indented row with the following indented rows and join them as a single "line".
- Filter "GJ" initial lines only.
Here is the code:
def iter_lines(fo):
cur_line = []
for row in fo:
if not row.startswith(' ') and cur_line:
yield ' '.join(cur_line)
cur_line = [] # reset the cache
cur_line.append(row.strip())
# yield the last line
if cur_line:
yield ' '.join(cur_line)
with open(input_file, encoding="utf8") as fo:
for line in iter_lines(fo):
if line.startswith('GJ'):
keywords = [k.strip() for k in line[2:].split(';')]
print(keywords)
You can use iter to convert your object into an iterable which supports next.
irofile = iter(rofile)
for line in irofile:
print line
if(line == 'foo'):
line = next(irofile) #BEWARE, This could raise StopIteration!
print line
As pointed out in the comments, if your object is already an iterator, then you don't need to worry about iter (this is the case with file objects). However, I leave it here as it works for the case of any arbitrary iterable (e.g. lists).
Depending on the type of object that rofile is, I can think of a couple of ways to do this.
List of strings
If you can get it to be simply a list of strings that make up the lines of the file:
for index, line in enumerate(rofile):
if line == 'foo':
for a in range(index, index + HOW_MANY_LINES_YOU_WANT):
print rofile[a]
Iterable
If the file is already an iterable:
for line in rofile:
print line
if line == 'foo':
for a in range(3): # Just do it 3 times
print line.next()
# After this happens and the for loop is restarted,
# it will print the line AFTER
You can see in this quickie example I wrote that it'll work this way as an iterable:
>>> k = iter([1,2,3,4])
>>> for a in k:
print 'start loop'
print a
if a == 2:
print 'in if'
print k.next()
print 'end if'
print 'end loop'
start loop
1
end loop
start loop
2
in if
3
end if
end loop
start loop
4
end loop
Just use the index.
def openFood():
with open("FoodList.txt") as f:
lines = f.readlines()
for i in range(len(lines)-1):
if 'Food' in lines[i]:
print(lines[i+1])
openFood()
Can you try the following:
def openFood():
with open("FoodList.txt") as f:
lines = f.readlines()
for ind, line in enumerate(lines):
if 'Food' in line:
try:
print(lines[ind + 1])
except:
print('No line after "Food"')
openFood()
You don't need to call next(). You are already iterating over the lines of the file, so, don't do anything, and the next line will come at the next iteration.
elif clientid not in line:
pass
Unrelated to file reading: You if-elseif-else doesn't make sense. clientid in line is either true or false, so it doesn't make sense to have 3 conditions. Just remove the middle elif altogether`
for loop already calls next for you.
Since you are reading a csv file (a file with values separated by commas) you should use the csv module - it automatically splits each line for you, so you don't have to slice each line yourself.
To further help you I also removed the globals and used parameter passing to pass the variable to the other function. Also I removed the recursive call to main() and used a loop to repeat the search. If you enter the empty string (just press enter), it should exit the loop and finish the program.
import csv
def main():
print("===================")
print("=Activity Recorder=")
print("===================")
while True:
clientid=input("Please enter the client ID: ")
print("")
if not clientid:
break
with open ("clientIntensity.txt") as f:
search = csv.reader(f, delimiter=',')
for row in search:
if row[0] == clientid:
idin = row[1]
print ("Intensity = ", idin)
acti(idin)
break
else:
print('ERROR: Not found')
def acti(idin):
if idin == "High":
print("Activites = Running, Swimming, Aerobics, Football, Tennis")
elif idin == "Moderate":
print("Activities = Walking, Hiking, Cleaning, Skateboarding, Basketball")
else:
print("ERROR: Unknown idin")
next(f) consumes the next line, each line can only be read once, so you need to reorder how you read lines. This should work
with open(filename) as f:
previous = None
current = next(f).strip()
for line in f:
line=line.strip()
print(previous, current, line)
previous = current
current = line
Output:
None line1 line2
line1 line2 line3
line2 line3 line4
The issue that you're encountering is that next(f) iterates the file position, so for each iteration of the for loop, two lines are actually being read.
You can accomplish this by changing your approach slightly. Instead of line being the center element, you should have line refer to the last element, and maintain previous-previous as well as previous.
prevprev = None
with open(filename, 'r') as f:
# Read the first line before the loop
prev = f.readline().strip()
for line in f:
line = line.strip()
print(prevprev, prev, line)
prevprev = prev
prev = line
Output:
None line1 line2
line1 line2 line3
line2 line3 line4
you can use xml.dom.minidom
Assuming your xml data is in a file
from xml.dom.minidom import parse
xmldata = open("abc.txt", "r")
domdata = parse(xmldata)
def getDescriptionData(title):
titledata = [x.toxml().lstrip('<title>').rstrip('</title>') for x in domdata.getElementsByTagName('title')]
descriptiondata = [x.toxml().lstrip('<description>').rstrip('</description>') for x in domdata.getElementsByTagName('description')]
l = [v for (x, v) in zip(titledata, descriptiondata) if x == title]
if l:
return l[0]
return None
print getDescriptionData('Lake Louis')
Output:
Open / Past 48 Hours: 2cm / Primary: / Base Depth: 162cm
You can also look into SAX XML parsing
Try using itertools.dropwhile():
Python 2.7.3 (default, Sep 4 2012, 20:19:03)
[GCC 4.2.1 20070831 patched [FreeBSD]] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>> import itertools
>>> src="foo\nbar\nbas\n"
>>> notfoundyet=True
>>> def findthing(x):
... global notfoundyet
... currently=notfoundyet
... notfoundyet=x!="bar"
... return currently
...
>>> itertools.dropwhile(findthing, src.split("\n"))
<itertools.dropwhile object at 0x8017d92d8>
>>> for x in _:
... print x
...
bas
If you just want to skip over lines not starting with #, there's a much easier way to do this:
file_handler = open(fname, 'r')
for line in file_handler:
if line[0] != '#':
continue
# now do the regular logic
print line
Obviously this kind of simplistic logic won't work in all possible cases. When it doesn't, you have to do exactly what the error implies: either use iteration consistently, or use read methods consistently. This is going to be more tedious and error-prone, but it's not that bad.
For example, with readline:
while True:
line = file_handler.readline()
if not line:
break
if line[0] == '#':
print line
else:
line2 = file_handler.readline()
print line2
Or, with iteration:
lines = file_handler
for line in file_handler:
if line[0] == '#':
print line
else:
print line
print next(file_handler)
However, that last version is sort of "cheating". You're relying on the fact that the iterator in the for loop is the same thing as the iterable it was created from. This happens to be true for files, but not for, say, lists. So really, you should do the same kind of while True loop here, unless you want to add an explicit iter call (or at least a comment explaining why you don't need one).
And a better solution might be to write a generator function that transforms one iterator into another based on your rule, and then print out each value iterated by that generator:
def doublifier(iterable):
it = iter(iterable)
while True:
line = next(it)
if line.startswith('#'):
yield line, next(it)
else:
yield (line,)
file_handler = open(fname, 'r')
for line in file_handler:
if line.startswith('#'): # <<< comment 1
print line
else:
line2 = next(file_handler) # <<< comment 2
print line2
Discussion
Your code used a single equal sign, which is incorrect. It should be double equal sign for comparison. I recommend to use the .startswith() function to enhance code clarity.
Use the
next()function to advance to the next line since you are usingfile_handleras an iterator.