75
votes

I just came across this piece of code

while 1:
    line = data.readline()
    if not line:
        break
    #...

and thought, there must be a better way to do this, than using an infinite loop with break.

So I tried:

while line = data.readline():
    #...

and, obviously, got an error.

Is there any way to avoid using a break in that situation?

Edit:

Ideally, you'd want to avoid saying readline twice... IMHO, repeating is even worse than just a break, especially if the statement is complex.

11
While this is a good question and I think the for line in data solution is a good fit for this specific problem, I don't think there's anything wrong with the while True: ... break idiom. Don't be afraid of it. :-) - Kirk Strauser
These answers provide alternatives to assignment in the conditional of the while-loop, but really don't answer the question: is there a way to do assignment in the while-loop? I'm running into this same problem, trying to do while (character = string[i]): I know that a for-loop is a better way to iterate over a string, but my conditional is actually much more complex than this, and I want to do this assignment as the right-hand side of an "or" within the conditional. - user2760926
@KirkStrauser The problem with the break construction is, that it is using four lines to express something, which other languages can do in just one line. However it does the right thing. None of the answers given so far has provided a better general purpose solution. They either only work with iterators or duplicate the assignment, which is worse than three extra lines of code for the break version. - kasperd

11 Answers

29
votes

If you aren't doing anything fancier with data, like reading more lines later on, there's always:

for line in data:
    ... do stuff ...
72
votes

Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), it's now possible to capture the condition value (data.readline()) of the while loop as a variable (line) in order to re-use it within the body of the loop:

while line := data.readline():
  do_smthg(line)
40
votes

Try this one, works for files opened with open('filename')

for line in iter(data.readline, b''):
20
votes

This isn't much better, but this is the way I usually do it. Python doesn't return the value upon variable assignment like other languages (e.g., Java).

line = data.readline()
while line:
    # ... do stuff ... 
    line = data.readline()
6
votes

Like,

for line in data:
    # ...

? It large depends on the semantics of the data object's readline semantics. If data is a file object, that'll work.

5
votes

As of python 3.8 (which implements PEP-572) this code is now valid:

while line := data.readline():
   # do something with line 
4
votes
for line in data:
    ... process line somehow....

Will iterate over each line in the file, rather than using a while. It is a much more common idiom for the task of reading a file in my experience (in Python).

In fact, data does not have to be a file but merely provide an iterator.

2
votes

You could do:

line = 1
while line:
    line = data.readline()
2
votes

If data has a function that returns an iterator instead of readline (say data.iterate), you could simply do:

for line in data.iterate():
    #...
2
votes

If data is a file, as stated in other answers, using for line in file will work fine. If data is not a file, and a random data reading object, then you should implement it as an iterator, implementing __iter__ and next methods.

The next method should to the reading, check if there is more data, and if not, raise StopIteration. If you do this, you can continue using the for line in data idiom.

2
votes

According to the FAQ from Python's documentation, iterating over the input with for construct or running an infinite while True loop and using break statement to terminate it, are preferred and idiomatic ways of iteration.