0

Attempting to use matplotlib to write out to an iostream then display that data in another matplotlib plot (started by following: Write Matplotlib savefig to html). For efficiency purposes, I want to avoid writing the image to disk.

Here's the code:

import cStringIO
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt2
import matplotlib.image as mpimg

sio = cStringIO.StringIO()
plt.savefig(sio, format='png')

# I should mention at this point here that the sio object is sent through a 
# pipe between two processes (so it has been pickled)    

imgplt = plt2.imshow(mpimg.imread(sio.getvalue().encode("base64").strip()))
# this line generates the following error.  As well as several variations 
#   including specifying 'png'

The error returned is: IOError: [Errno 22] invalid mode ('rb') or filename: 'iVBORw...followed by a long string with the data from the image'

I looked at the image.py file and it appears to be looking for a filename.

Thanks for taking a look.

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • I made this question consistent with the accepted answer. Any further problems are now open for discussion in [this question](https://stackoverflow.com/questions/47023141/sending-data-bytesio-buffer-through-a-pipe-works-but-causes-a-fatal-python-exc). – ImportanceOfBeingErnest Oct 30 '17 at 20:15

1 Answers1

1

imread interpretes the string given to it as filename. Instead one would need to supply a file-like object.

You would get such file-like object as the buffer itself. However, StringIO may not be well suited. If you use BytesIO, you can directly read in the buffer.

import io
import matplotlib.pyplot as plt

plt.plot([1,2,4,2])
plt.title("title")

buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)

imgplt = plt.imshow(plt.imread(buf))

plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Thanks for your response. I was able to clear a hurdle, I hadn't considered putting the imread in the process before the send. So it works well as shown but when I use multiprocessing and send/recv to the get the data to the main there is an msvc error. I updated the question above with the details. – user3701730 Oct 30 '17 at 17:21
  • At the moment I have no idea where the problem originates from, but it seems related to using the buffer. In that sense you can decide for yourself whether to wait for an answer here or whether to ask a new question about it. What would speak for asking a new question is that it would attract more attention and could be formulated more in the direction of "I can send data through a `Pipe` without problem, but when data originates from a `BytesIO` buffer, it causes a `Fatal Python error: PyEval_RestoreThread: NULL tstate`." – ImportanceOfBeingErnest Oct 30 '17 at 17:47
  • Note that you need to *call* close. `conn.close()` instead of `conn.close`. But that doesn't solve the problem. – ImportanceOfBeingErnest Oct 30 '17 at 17:49