classification
Title: fileinput module will read whole file into memory when using fileinput.hook_encoded due to codecs.StreamReader.readlines
Type: enhancement Stage: resolved
Components: IO Versions: Python 2.7
process
Status: closed Resolution: duplicate
Dependencies: Superseder: fileinput module will read whole file into memory when using fileinput.hook_encoded
View: 20501
Assigned To: Nosy List: gromgull, r.david.murray
Priority: normal Keywords:

Created on 2014-02-06 10:08 by gromgull, last changed 2014-02-06 14:10 by r.david.murray. This issue is now closed.

Messages (2)
msg210371 - (view) Author: Gunnar Aastrand Grimnes (gromgull) Date: 2014-02-06 10:08
When reading large files with fileinput, it will work as expected and only process a line at a time when used normally, but if you add an hook_encoded openhook it will read the whole file into memory before returning the first line. 

Verify by running this program on a large text file: 

import fileinput

for l in fileinput.input(openhook=fileinput.hook_encoded('iso-8859-1')):
    raw_input()

and check how much memory it uses. Remove the openhook and memory usage goes down to nothing.

The problem is that fileinput calls readlines with a size-hint and in codecs.StreamReader, readlines explicitly ignores this hint and reads all lines into memory. 

http://bugs.python.org/issue20501 is open for fixing up the documentation for fileinput, but a fix would also be nice.

I see two options: 

1. As suggested by r.david.murray: Give us a way of signaling to fileinput that it should not use readlines, for instance by setting buffer=None

2. Fix the codecs module to allow StreamReader to respect the hint if given. Although the comment there says it's no efficient way to do this, at least an inefficient way would be better than reading a possibly infinite stream in. A simple solution would be to repeatedly call readline. A more complicated solution would be to read chunks from the stream, and then encode them, just like the readline method does. 

BTW - this issue is py2.7 only, I tested a file object from io.open with encoding in 3.3 and it supports readlines just fine.
msg210381 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-02-06 14:10
Unfortunately, since 2.7 is in feature freeze, we can't add any new API there to allow a circumvention.  On the other hand, it sounds like Serhiy has come up with an actual fix in the other issue, based on the reason that it is not in fact a problem in 3.x (the io module is smarter than the codecs module in this context).

So, I'm going to close this issue...sorry you went to the extra effort of creating it to no purpose.
History
Date User Action Args
2014-02-06 14:10:06r.david.murraysetstatus: open -> closed

superseder: fileinput module will read whole file into memory when using fileinput.hook_encoded
nosy: + r.david.murray

messages: + msg210381
type: enhancement
resolution: duplicate
stage: resolved
2014-02-06 10:08:45gromgullcreate