8000 Merge pull request #13062 from anntzer/webserver-doc · matplotlib/matplotlib@49c9904 · GitHub
[go: up one dir, main page]

Skip to content
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 49c9904

Browse files
authored
Merge pull request #13062 from anntzer/webserver-doc
Update FAQ re: batch/webserver use.
2 parents 86d80aa + b58afd4 commit 49c9904

File tree

1 file changed

+39
-67
lines changed

1 file changed

+39
-67
lines changed

doc/faq/howto_faq.rst

Lines changed: 39 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -423,18 +423,12 @@ locators as desired because the two axes are independent.
423423
Generate images without having a window appear
424424
----------------------------------------------
425425

426-
The easiest way to do this is use a non-interactive backend (see
427-
:ref:`what-is-a-backend`) such as Agg (for PNGs), PDF, SVG or PS. In
428-
your figure-generating script, just call the
429-
:func:`matplotlib.use` directive before importing pylab or
430-
pyplot::
431-
432-
import matplotlib
433-
matplotlib.use('Agg')
434-
import matplotlib.pyplot as plt
435-
plt.plot([1,2,3])
436-
plt.savefig('myfig')
426+
Simply do not call `~matplotlib.pyplot.show`, and directly save the figure to
427+
the desired format::
437428

429+
import matplotlib.pyplot as plt
430+
plt.plot([1, 2, 3])
431+
plt.savefig('myfig.png')
438432

439433
.. seealso::
440434

@@ -454,7 +448,7 @@ the mainloop. Because this mainloop is blocking by default (i.e., script
454448
execution is paused), you should only call this once per script, at the end.
455449
Script execution is resumed after the last window is closed. Therefore, if
456450
you are using Matplotlib to generate only images and do not want a user
457-
interface window, you do not need to call ``show`` (see :ref:`howto-batch`
451+
interface window, you do not need to call ``show`` (see :ref:`howto-batch`
458452
and :ref:`what-is-a-backend`).
459453

460454
.. note::
@@ -641,66 +635,44 @@ Looking for something to do? Search for `TODO <../search.html?q=todo>`_
641635
or look at the open issues on github.
642636

643637

644-
645-
646638
.. _howto-webapp:
647639

648640
Matplotlib in a web application server
649641
======================================
650642

651-
Many users report initial problems trying to use Matplotlib in web
652-
application servers, because by default Matplotlib ships configured to
653-
work with a graphical user interface which may require an X11
654-
connection. Since many barebones application servers do not have X11
655-
enabled, you may get errors if you don't configure Matplotlib for use
656-
in these environments. Most importantly, you need to decide what
657-
kinds of images you want to generate (PNG, PDF, SVG) and configure the
658-
appropriate default backend. For 99% of users, this will be the Agg
659-
backend, which uses the C++
660-
`antigrain <http://antigrain.com>`_
661-
rendering engine to make nice PNGs. The Agg backend is also
662-
configured to recognize requests to generate other output formats
663-
(PDF, PS, EPS, SVG). The easiest way to configure Matplotlib to use
664-
Agg is to call::
665-
666-
# do this before importing pylab or pyplot
667-
import matplotlib
668-
matplotlib.use('Agg')
669-
import matplotlib.pyplot as plt
670-
671-
For more on configuring your backend, see :ref:`what-is-a-backend`.
672-
673-
Alternatively, you can avoid pylab/pyplot altogether, which will give
674-
you a little more control, by calling the API directly as shown in
675-
:doc:`/gallery/user_interfaces/canvasagg`.
676-
677-
You can either generate hardcopy on the filesystem by calling
678-
`.Figure.savefig()`::
679-
680-
# do this before importing pylab or pyplot
681-
import matplotlib
682-
matplotlib.use('Agg')
683-
import matplotlib.pyplot as plt
684-
fig = plt.figure()
685-
ax = fig.add_subplot(111)
686-
ax.plot([1,2,3])
687-
fig.savefig('test.png')
688-
689-
or by saving to a file handle::
690-
691-
import sys
692-
fig.savefig(sys.stdout)
693-
694-
Here is an example using `Pillow <https://pillow.readthedocs.io/en/latest/>`_.
695-
First, the figure is saved to a BytesIO object which is then fed to
696-
Pillow for further processing::
697-
698-
from io import BytesIO
699-
from PIL import Image
700-
imgdata = BytesIO()
701-
fig.savefig(imgdata, format='png')
702-
imgdata.seek(0) # rewind the data
703-
im = Image.open(imgdata)
643+
In general, the simplest solution when using Matplotlib in a web server is
644+
to completely avoid using pyplot (pyplot maintains references to the opened
645+
figures to make `~.matplotlib.pyplot.show` work, but this will cause memory
646+
leaks unless the figures are properly closed). Since Matplotlib 3.1, one
647+
can directly create figures using the `Figure` constructor and save them to
648+
in-memory buffers. The following example uses Flask_, but other frameworks
649+
work similarly::
650+
651+
import base64
652+
from io import BytesIO
653+
654+
from flask import Flask
655+
from matplotlib.figure import Figure
656+
657+
app = Flask(__name__)
658+
659+
@app.route("/")
660+
def hello():
661+
# Generate the figure **without using pyplot**.
662+
fig = Figure()
663+
ax = fig.subplots()
664+
ax.plot([1, 2])
665+
# Save it to a temporary buffer.
666+
buf = BytesIO()
667+
fig.savefig(buf, format="png")
668+
# Embed the result in the html output.
669+
data = base64.b64encode(buf.getbuffer()).decode("ascii")
670+
return f"<img src='data:image/png;base64,{data}'/>"
671+
672+
.. _Flask: http://flask.pocoo.org/
673+
674+
When using Matplotlib versions older than 3.1, it is necessary to explicitly
675+
instantiate an Agg canvas; see e.g. :doc:`/gallery/user_interfaces/canvasagg`.
704676

705677

706678
.. _howto-click-maps:

0 commit comments

Comments
 (0)
0