I have this code:
with open(inputfile, 'r') as infile:
for line in infile:
if line.startswith(">"):
print line
# keep printing until next ">" encountered; stop at that point
# and move on to next line that starts with ">"...But I don't know how to do that last part...keep printing lines in the file until I hit the next ">", at which point I need it to stop printing, find the next line that starts with ">", then start printing again.
I've searched like every google link for this. It has been asked a lot, but nowhere is there an explanation understand. Usually it's also some variation, such as print from the start until match, but I know how to do that. I need to print from match to match...
I think I can do this with enumerate() a list, and a while loop, but it requires I read the file into memory, which I don't want to do considering the files I need to work on are a few GB each and contain a few million lines, so I don't want to read the entire thing into a list...
The real problem I am having is how to access the "next line" after the line that contains ">"? next(infile) works, but only for the immediate next line. What if I need the next 2 or 3 lines? I tried the following inside the "if line.startswith" part:
line = next(infile)
while not line.startswith(">"):
print line
line = next(infile)But that doesn't work...(not entirely sure why, I assume next() can only take the immediate next line).
Anyone? Is there no default python function (that I can't find) that does this?
files are iterators (unlike lists) so you can just make a second for loop:
with open(inputfile, 'r') as infile:
for line in infile:
if line.startswith(">"):
print line, # comma on the end prevents the double spacing from printing a file line
for line in infile:
print line,
if line.startswith(">"):
break # stop this inner for loop; outer loop picks up on the next line
Edit: I get the feeling I don't understand your problem. Can you show some example data and what you want out?
An easy way to do it would be something like this:
should_print = False
with open(inputfile, 'r') as infile:
for line in infile:
if line.startswith(">"):
# should_print becomes True if was False and becomes False if was True
should_print = not should_print
if should_print:
print(line)
regex - Read file until specific line in python - Stack Overflow
Reading a file until a specific character in python - Stack Overflow
python 3.x - Reading txt file till certain point and then create new txt file out of existing file - Software Engineering Stack Exchange
text - Read Up Until a Point Python - Stack Overflow
The built-in str.partition() method will do this for you. Unlike str.split() it won't bother to cut the rest of the str into different strs.
text = raw_input("Type something:")
left_text = text.partition("!")[0]
Explanation
str.partition() returns a 3-tuple containing the beginning, separator, and end of the string. The [0] gets the first item which is all you want in this case. Eg.:
"wolfdo65gtornado!salmontiger223".partition("!")
returns
('wolfdo65gtornado', '!', 'salmontiger223')
>>> s = "wolfdo65gtornado!salmontiger223"
>>> s.split('!')[0]
'wolfdo65gtornado'
>>> s = "wolfdo65gtornadosalmontiger223"
>>> s.split('!')[0]
'wolfdo65gtornadosalmontiger223'
if it doesnt encounter a "!" character, it will just grab the entire text though. if you would like to output an error if it doesn't match any "!" you can just do like this:
s = "something!something"
if "!" in s:
print "there is a '!' character in the context"
else:
print "blah, you aren't using it right :("
This is pretty straight forward, you can terminate a loop early with a break statement.
filename = 'somefile.txt'
with open(filename, 'r') as input:
for line in input:
if 'indicator' in line:
break
Using with creates a compound statement that ensures that upon entering and leaving the scope of the with statement __enter__() and __exit__() will be called respectively. For the purpose of file reading this will prevent any dangling filehandles.
The break statement tells the loop to terminate immediately.
Use iter()'s sentinel parameter:
with open('test.txt') as f:
for line in iter(lambda: f.readline().rstrip(), 'SPECIFIC LINE'):
print(line)
output:
file start here..
some data...
Reference: https://docs.python.org/2/library/functions.html#iter
The easiest way would be to read the file in as a single string and then split it across your separator:
with open('myFileName') as myFile:
text = myFile.read()
result = text.split(separator) # use your \-1 (whatever that means) here
In case your file is very large, holding the complete contents in memory as a single string for using .split() is maybe not desirable (and then holding the complete contents in the list after the split is probably also not desirable). Then you could read it in chunks:
def each_chunk(stream, separator):
buffer = ''
while True: # until EOF
chunk = stream.read(CHUNK_SIZE) # I propose 4096 or so
if not chunk: # EOF?
yield buffer
break
buffer += chunk
while True: # until no separator is found
try:
part, buffer = buffer.split(separator, 1)
except ValueError:
break
else:
yield part
with open('myFileName') as myFile:
for chunk in each_chunk(myFile, separator='\\-1\n'):
print(chunk) # not holding in memory, but printing chunk by chunk
I used "*" instead of "-1", I'll let you make the appropriate changes.
s = '1.Hai\n2.Bye*3.Hello\n4.OAPd*'
temp = ''
results = []
for char in s:
if char is '*':
results.append(temp)
temp = []
else:
temp += char
if len(temp) > 0:
results.append(temp)
Read line by line. Use #main as a flag to start processing. Use #extra as a flag to stop processing.
start = '#main'
end = '#extra'
numbers = []
file_handler = open('read_up_to_a_point.txt')
started = False
for line in file_handler:
if end in line:
started = False
if started:
numbers.append(line.strip())
if start in line:
started = True
file_handler.close()
print numbers
sample output
python read_up_to_a_point.py ['60258960', '33031674', '72302403']
You're pretty close, as you are. You just need to modify your list slice to chop off the last two lines in the file along with the first two. readlines will naturally return a list where each item is one line from the file. However, it will also have the 'newline' character at the end of each string, so you may need to filter that out.
with open("myfile.txt") as myfile:
# Get only numbers
read = myfile.readlines()[2:-2]
# Remove newlines
read = [number.strip() for number in read]
print read
useful = []
with open ("Report.txt", "r") as myfile:
for line in myfile:
if "===" in line:
break
for line in myfile:
useful.append(line)
a_string = "".join(useful)
I would however prefer to hide it away in a generator, like this:
def report_iterator():
with open ("Report.txt", "r") as myfile:
for line in myfile:
if "===" in line:
break
for line in myfile:
yield line
for line in report_iterator():
# do stuff with line
All the filtering and nitpicking is done in the generator function, and you can separate the logic of "filtering input" from the logic of "working with the input".
You could read line by line, and by default not store the lines. When you get the line starting with '==', then all lines you read until you read the second '==' line you store in your string or list.
You need to use a byte string as the pattern in your regex, something like the following should work:
if re.search(b"enum " + enum_name.encode('utf-8'), line):
...
The enum_name.encode('utf-8') here is used to convert the user input to a bytes object, depending on your environment you may need to use a difference encoding.
Note that if your regex is really this simple, then you can probably just use a substring search instead.
You don't need re. Try
if "enum " + enum_name in line:
Reading with 'b' is mostly about line endings.
Look at the docs. Read until wants the expected string as a positional argument and an optional timeout. I would do it like this:
>>> try:
... response = tn.read_until(">", timeout=120) #or whatever timeout you choose.
... except EOFError as e:
... print "Connection closed: %s" % e
>>> if ">" in response:
... action1
... else:
... action2
If you want multiple different characters you can use read_some()
>>> while True: #really you should set some sort of a timeout here.
... r = tn.read_some()
... if any(x in r for x in ["#", ">"]):
... break
Better yet just use:
buff_tpl = tn.expect(["#", ">"])
This will return a tuple with three items, the first (index of 0) is the index of the list item matched, the second is and object matched, and the third is the output text.
You can print the buffer output using buff_tpl[2], and know which item matched using buff_tpl[0]
StockSearch = input("Search For Product (Name Or Code):\n")
found = False
with io.open('/home/jake/Projects/Stock','r', encoding='utf8') as f:
for line in f:
line = line.rstrip('\n')
if StockSearch == line:
print(line)
found = True
break
if not found:
print("Nothing found")
This seems similar to a pattern I saw on a 'Pythonic' coding video by Raymond Hettinger. It's called iterating with a sentinel value.
The format goes like this:
with open('filename.txt') as f:
blocks = []
read_block = partial(f.read, 32)
for block in iter(read_block, ''):
blocks.append(block)
In your case, you would replace '' with your stop value.
If you simply want the block of text between Start and End, you can do something simple like:
with open('test.txt') as input_data:
# Skips text before the beginning of the interesting block:
for line in input_data:
if line.strip() == 'Start': # Or whatever test is needed
break
# Reads text until the end of the block:
for line in input_data: # This keeps reading the file
if line.strip() == 'End':
break
print line # Line is extracted (or block_of_lines.append(line), etc.)
In fact, you do not need to manipulate line numbers in order to read the data between the Start and End markers.
The logic ("read until…") is repeated in both blocks, but it is quite clear and efficient (other methods typically involve checking some state [before block/within block/end of block reached], which incurs a time penalty).
Here's something that will work:
data_file = open("test.txt")
block = ""
found = False
for line in data_file:
if found:
block += line
if line.strip() == "End": break
else:
if line.strip() == "Start":
found = True
block = "Start"
data_file.close()
First time posting here, I think I posted the "code" part correctly but didn't know about the output part.
I created a class to help me read and write into an instrument using serial port. However, recently I found an issue that I think it's due to sending multiple write commands and I only need to read when I query the instrument. When I send regular write commands, the instrument outputs text indicating the changes made as shown below:
self.id.write(str.encode("send write command\r"))
time.sleep(1)
self.id.write(str.encode("get status\r"))
output=self.id.read_until(str.encode(">>\r"))When sending the write command, it will output a status as:
>>write command:
Configured state to: 0A
>>
>>get status
status is configured to: BB
What I think it's happening is that when I use the read_until() , it will start reading from the "send write" command instead of the "get status" because when I look at the text captured it corresponds to the "Configured state to: 0A" line.
My question is: How do I get the code to read only from the time I send the "get status" command? I have thought about reading the line when I send the "write command" and not doing anything with it, but I think there might be another option.