You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
numpy.fromfile does not accept StringIO object (Trac #1634) #2230
Still present; the number parsing in numpyos needs to read from an OS-level file descriptor. Fix nontrivial (file-like objects require you to go through python to get characters, and don't provide ungetc).
If it helps anyone else, I was also hitting this same problem with a third-party library using numpy.fromfile. I really wanted to stream an in-memory byte string to it rather than writing a temporary file to disk.
I finally found that tempfile.SpooledTemporaryFile does the trick. You can create a SpooledTemporaryFile, write the bytes to it (in memory) and supply this to numpy.fromfile without errors...in my experience.
Actually, I need to amend my last comment. It looked like everything was working, but I suspect a file intermediate is still being used because the documentation for SpooledTemporaryFile says that the contents will be written to disk if fileno() is called, and I've seen that this is exactly what's happening with numpy.fromfile. So it's probably not avoiding the to disk problem. YMMV
glad to have found this issue... I wanted to load an array from a compressed file and thought np.fromfile(...LZMAFile...) would work. it doesn't, it uses fileno() of the compressed file and interprets the compressed data rather than the uncompressed one.
plain = bytes.fromhex("76543210")
compressed = lzma.compress(plain)
lzfile = lzma.open(io.BytesIO(compressed))
print(x.read().hex())
x.seek(0)
print(np.fromfile(x, dtype=np.uint8)) # this fails because the file object has no fileno method
I think this would be a really useful feature to have. The only workaround would be to .read() from that file and pass the bytes object to np.frombuffer(). I'm unsure if that's efficient.
@crackwitz using np.frombuffer should be just as efficient. If you check the result from it, you will see that its res.flags shows that it is readonly, which is because the bytes object returned by file.read() is readonly. So that is the only thing you are losing speed wise: if you want a writeable array, you will need to make a single copy (there may be some small efficiency difference due to different methods of reading and small overheads if you are loading small files).
Also, the title should change to reflect that io.BytesIO is not accepted either. This is not an issue with just text streams, but with any stream that is not an actual on-disk local file.
For those in need of a workaround to this limitation, here's a wrapper based on Teledyne-Marine/pyread7k#14's solution:
AnyFile=typing.Union[str, bytes, os.PathLike, io.IOBase]
defnumpy_fromfile(file: AnyFile, dtype: numpy.typing.DTypeLike=float, count: int=-1):
"""numpy.fromfile() wrapper, handling io.BytesIO file-like streams. Numpy requires open files to be actual files on disk, i.e., must support file.fileno(), so it fails with file-like streams such as io.BytesIO(). If numpy.fromfile() fails due to no file.fileno() support, this wrapper reads the required bytes from file and redirects the call to numpy.frombuffer(). See https://github.com/numpy/numpy/issues/2230 """try:
returnnumpy.fromfile(file, dtype=dtype, count=count)
exceptio.UnsupportedOperationase:
ifnot (e.argsande.args[0] =='fileno'andisinstance(file, io.IOBase)):
raise# Nothing I can do about itdtype=numpy.dtype(dtype)
buffer=file.read(dtype.itemsize*count)
returnnumpy.frombuffer(buffer, dtype=dtype, count=count)
Activity
numpy-gitbot commentedon Oct 19, 2012
@pv wrote on 2010-10-28
Ditto for tofile.
charris commentedon Jan 16, 2014
@cgohlke @pv Is this fixed now?
astrojuanlu commentedon Nov 13, 2014
I checked this is still the case in NumPy 1.9 and both Python 2 and 3.
aarchiba commentedon Aug 26, 2015
Still present; the number parsing in numpyos needs to read from an OS-level file descriptor. Fix nontrivial (file-like objects require you to go through python to get characters, and don't provide ungetc).
josechavezm commentedon Jun 22, 2017
Is there a workaround or something?
nikita6187 commentedon Jul 27, 2017
Error still not fixed
LeeKamentsky commentedon Aug 11, 2017
And it's broken @cgohlke 's work-around because now it throws TypeError instead of IOError.
drkeoni commentedon Sep 12, 2018
If it helps anyone else, I was also hitting this same problem with a third-party library using
numpy.fromfile. I really wanted to stream an in-memory byte string to it rather than writing a temporary file to disk.I finally found that
tempfile.SpooledTemporaryFiledoes the trick. You can create aSpooledTemporaryFile, write the bytes to it (in memory) and supply this tonumpy.fromfilewithout errors...in my experience.drkeoni commentedon Sep 12, 2018
Actually, I need to amend my last comment. It looked like everything was working, but I suspect a file intermediate is still being used because the documentation for
SpooledTemporaryFilesays that the contents will be written to disk iffileno()is called, and I've seen that this is exactly what's happening withnumpy.fromfile. So it's probably not avoiding the to disk problem. YMMVcrackwitz commentedon Feb 18, 2019
glad to have found this issue... I wanted to load an array from a compressed file and thought np.fromfile(...LZMAFile...) would work. it doesn't, it uses fileno() of the compressed file and interprets the compressed data rather than the uncompressed one.
I think this would be a really useful feature to have. The only workaround would be to
.read()from that file and pass the bytes object tonp.frombuffer(). I'm unsure if that's efficient.seberg commentedon Feb 18, 2019
@crackwitz using
np.frombuffershould be just as efficient. If you check the result from it, you will see that itsres.flagsshows that it is readonly, which is because thebytesobject returned byfile.read()is readonly. So that is the only thing you are losing speed wise: if you want a writeable array, you will need to make a single copy (there may be some small efficiency difference due to different methods of reading and small overheads if you are loading small files).cgohlke commentedon Feb 19, 2019
For such simple cases,
readintois also an option:mattip commentedon Feb 19, 2019
@cgohlke nice. Where in the documentation should we add that to make it more discoverable?
jakirkham commentedon Nov 15, 2019
Just tried this recently and got the following error.
MestreLion commentedon Oct 21, 2021
Any news on this? Is switching from
np.fromfile(f, ...)tonp.frombuffer(f.read(x), ...)the only standard, non-disk option?MestreLion commentedon Oct 22, 2021
Also, the title should change to reflect that
io.BytesIOis not accepted either. This is not an issue with just text streams, but with any stream that is not an actual on-disk local file.MestreLion commentedon Oct 22, 2021
For those in need of a workaround to this limitation, here's a wrapper based on Teledyne-Marine/pyread7k#14's solution:
Can anyone verify if this a proper workaround?
marscher commentedon Aug 29, 2023
thanks @MestreLion!
This works for me.