>>> with open("using_python_to_profit") as f:
... first, *_, last = f.readlines()
Or more simply:
first, *_, last = f
Though I don't like how '_' can keep a potentially arbitrary amount of data in memory.
There's also a question of what to do when there is only one line in the file, or zero lines. The above raises a ValueError. An alternative solution, which uses None if there are no lines, and make first == last if there is one line, and which works with Python 2.6 and later, is:
with open("using_python_to_profit") as f:
first = last = next(f, None)
if first is not None:
for last in f:
pass
The test for 'first is not None' is because next(f) can raise a StopIteration, but if the file is written to again, next(f) will return the next line.
% touch empty.txt
% ls -l empty.txt
-rw-r--r-- 1 dalke admin 0 Feb 11 01:34 empty.txt
% python
Python 3.3.0 (default, Mar 12 2013, 09:53:08)
[GCC 4.2.1 Compatible Apple Clang 3.1 (tags/Apple/clang-318.0.54)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open("empty.txt")
>>> next(f)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> ^Z
Suspended
% echo "Hello!" >> empty.txt
% fg
python
>>> next(f)
'Hello!\n'
Yes, according to the iterator specification, once an iterator raises a StopIteration exception, subsequent calls are always supposed to raise StopIteration. According to the documentation, file iterators are "broken". Quoting from https://docs.python.org/3.4/library/stdtypes.html :
Once an iterator’s __next__() method raises StopIteration, it must continue
to do so on subsequent calls. Implementations that do not obey this property
are deemed broken.
Sigh. Time to report that bug. Well, need to reproduce it with the most recent Python first.
2 comments
[ 3.4 ms ] story [ 17.2 ms ] threadThere's also a question of what to do when there is only one line in the file, or zero lines. The above raises a ValueError. An alternative solution, which uses None if there are no lines, and make first == last if there is one line, and which works with Python 2.6 and later, is:
The test for 'first is not None' is because next(f) can raise a StopIteration, but if the file is written to again, next(f) will return the next line. Yes, according to the iterator specification, once an iterator raises a StopIteration exception, subsequent calls are always supposed to raise StopIteration. According to the documentation, file iterators are "broken". Quoting from https://docs.python.org/3.4/library/stdtypes.html : Sigh. Time to report that bug. Well, need to reproduce it with the most recent Python first.