Differences between revisions 22 and 24 (spanning 2 versions)
Revision 22 as of 2008-07-08 11:27:43
Size: 7541
Editor: localhost
Comment: converted to 1.6 markup
Revision 24 as of 2009-09-09 11:04:40
Size: 9104
Comment: If you have any problems with the above please let me know - werner.bruhin at free.fr
Deletions are marked like this. Additions are marked like this.
Line 32: Line 32:
Line 35: Line 34:
Line 66: Line 64:

Line 85: Line 81:
    data_files=[matplotlib.get_py2exe_datafiles()]     data_files=matplotlib.get_py2exe_datafiles()
Line 88: Line 84:
Line 90: Line 85:
--~~~~
In this example, a simple program was created where a matplotlib figure canvas is placed in a PyQt child window. In order to compile it with py2exe and matplotlib 0.91.2 with Python 2.5, it is necessary to include the necessary modules and then add the data files properly. On this system, the matplotlib was installed to the folder Python25\Lib\site-packages. Within the matplotlib folder, the matplotlib-data is saved in mpl-data.  
--~~~~ In this example, a simple program was created where a matplotlib figure canvas is placed in a PyQt child window. In order to compile it with py2exe and matplotlib 0.91.2 with Python 2.5, it is necessary to include the necessary modules and then add the data files properly. On this system, the matplotlib was installed to the folder Python25\Lib\site-packages. Within the matplotlib folder, the matplotlib-data is saved in mpl-data.
Line 98: Line 92:
Line 100: Line 95:
# Used successfully in Python2.5 with matplotlib 0.91.2 and PyQt4 (and Qt 4.3.3)  # Used successfully in Python2.5 with matplotlib 0.91.2 and PyQt4 (and Qt 4.3.3)
Line 113: Line 108:
                               "matplotlib.figure","pylab", "numpy", "matplotlib.numerix.fft", 
                               "matplotlib.numerix.linear_algebra", "matplotlib.numerix.random_array", 
                               "matplotlib.backends.backend_tkagg"], 
                'excludes': ['_gtkagg', '_tkagg', '_agg2', '_cairo', '_cocoaagg', 
                               "matplotlib.figure","pylab", "numpy", "matplotlib.numerix.fft",
                               "matplotlib.numerix.linear_algebra", "matplotlib.numerix.random_array",
                               "matplotlib.backends.backend_tkagg"],
                'excludes': ['_gtkagg', '_tkagg', '_agg2', '_cairo', '_cocoaagg',
Line 121: Line 116:
       }               }
Line 123: Line 118:
# Save matplotlib-data to mpl-data ( It is located in the matplotlib\mpl-data  # Save matplotlib-data to mpl-data ( It is located in the matplotlib\mpl-data
Line 129: Line 124:
                  (r'mpl-data', [r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']),                    (r'mpl-data', [r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']),
Line 136: Line 131:
= Excluding some backends =
If you omit some backends you must make sure it isn't the default - for example if you package WX backend and not Tcl/Tk:
{{{
}}}
The default backend is configured in mpl-data/matplotlib.conf. You can override the configuration in your program by doing for example:
{{{
import matplotlib
matplotlib.use('wxagg') # overrule configuration
import pylab}}}
Line 138: Line 141:
Line 142: Line 144:

= MPL datafiles etc with Python 2.5 and MPL 0.99 =
Using matplotlib.get_py2exe_datafiles() helps to make this really easy now.

Following is copy/paste from my larger setup.py, but it should work.

{{{
#!python
from distutils.core import setup
import py2exe

# my setup.py is based on one generated with gui2exe, so data_files is done a bit differently
data_files = []

import matplotlib as mpl
data_files += mpl.get_py2exe_datafiles()

setup(
    console=['test.py'],
    options={
             'py2exe': {
                        'packages' : ['pytz', ],
                       }
            },
    data_files=data_files
)
}}}

Note that I did not need to define matplotlib in packages and this works for me using the wxAgg backend.

There is one problem outstanding in 0.99 and that has to do with this kind of code:
"psd.__doc__ = psd.__doc__ % kwdocd"

It cause a TypeError exception if one uses ""optimize": 2," in ones setup.py.

My work around is to change that type of code to:
if psd.__doc__ is not None:
    psd.__doc__ = psd.__doc__ % kwdocd
else:
    psd.__doc__ = ""

Reported this to the mpl list, hopefully a better solution is found for this.

Introduction

MatPlotLib is a module to produce nice-looking plots in Python using a wide variety of back-end packages, at least one of which is likely to be available for your system. This ability to do things in a generic fashion makes this a simple system to use, but it gets complicated if you wish to distribute an executable instead of scripts. This page describes what I had to do to make matplotlib work with py2exe.

Special content for setup.py to use matplotlib

   1 # We need to import the glob module to search for all files.
   2 import glob
   3 
   4 # We need to exclude matplotlib backends not being used by this executable.  You may find
   5 # that you need different excludes to create a working executable with your chosen backend.
   6 # We also need to include matplotlib.numerix.random_array
   7 opts = {
   8     'py2exe': { 'includes': 'matplotlib.numerix.random_array',
   9                 'excludes': ['_gtkagg', '_tkagg'],
  10                 'dll_excludes': ['libgdk-win32-2.0-0.dll',
  11                                  'libgobject-2.0-0.dll']
  12               }
  13        }
  14 
  15 # Additional data files are required by matplotlib.  Note that the glob.glob routine
  16 # doesn't seem to pick up the .matplotlib resource file, so I copy that separately.
  17 # Do the same if you need to
  18 setup(
  19     data_files = [(r'matplotlibdata', glob.glob(r'c:\python24\share\matplotlib\*')),
  20                   (r'matplotlibdata', [r'c:\python24\share\matplotlib\.matplotlibrc'])],
  21     name = 'demo',
  22     description = 'MatPlotLib Demo Program',
  23     console = ['demo.py']
  24     )

Copying PyTZ folder

Now copy pytz folder from C:\Python24\Lib\site-packages to your dist/ folder and you're done!

Update for newer versions of matplotlib

Recent versions of matplotlib (this is tested with 0.87) have changed the location where data files are found. Here is a sample setup.py that works with simple matplotlib samples. It produces massive distributions - more work needs to be done on how to exclude unused backends.

   1 from distutils.core import setup
   2 import py2exe
   3 
   4 from distutils.filelist import findall
   5 import os
   6 import matplotlib
   7 matplotlibdatadir = matplotlib.get_data_path()
   8 matplotlibdata = findall(matplotlibdatadir)
   9 matplotlibdata_files = []
  10 for f in matplotlibdata:
  11     dirname = os.path.join('matplotlibdata', f[len(matplotlibdatadir)+1:])
  12     matplotlibdata_files.append((os.path.split(dirname)[0], [f]))
  13 
  14 
  15 setup(
  16     console=['test.py'],
  17     options={
  18              'py2exe': {
  19                         'packages' : ['matplotlib', 'pytz'],
  20                        }
  21             },
  22     data_files=matplotlibdata_files
  23 )

An easier way to get the list of datafiles

Even more recent version of MatPlotLib(Version 0.90 at least, maybe earlier versions) have a method named matplotlib.get_py2exe_datafiles() which returns a tuple that is ready for use in the data_files argument to distutils.setup(). A minimal setup.py utilizing this method would look something like this:

   1 from distutils.core import setup
   2 import py2exe
   3 
   4 import matplotlib
   5 
   6 setup(
   7     console=['test.py'],
   8     options={
   9              'py2exe': {
  10                         'packages' : ['matplotlib', 'pytz'],
  11                        }
  12             },
  13     data_files=matplotlib.get_py2exe_datafiles()
  14 )

Setup.py using py2exe with Python2.5 and matplotlib 0.91.2

--~~~~ In this example, a simple program was created where a matplotlib figure canvas is placed in a PyQt child window. In order to compile it with py2exe and matplotlib 0.91.2 with Python 2.5, it is necessary to include the necessary modules and then add the data files properly. On this system, the matplotlib was installed to the folder Python25\Lib\site-packages. Within the matplotlib folder, the matplotlib-data is saved in mpl-data.

Using the above methods would result in the classic "RuntimeError: Could not find the matplotlib data files" error. Furthermore, using the method with data_files = matplotlib.get_py2exe_datafiles(), py2exe returns an error saying that 'split' is not a valid method for this object. Another problem when using glob, the and a * is located in the argument, glob will search for everything, including folders. Doing this will give you an error when compiling saying that 'fonts' is not a file. So you need to add the contents from mpl-data\fonts and mpl-data\images individually.

Ensure that the first entry in the tuple in the list 'data_files' is matches the actual matplotlib data folder; in this case 'mpl-data' (and then later mpl-data\fonts and mpl-data\images). Also, the file matplotlibrc file is not returned by 'glob' so it is also added manually.

This is modified from the above setup.py under Special content for setup.py to use matplotlib

   1 # Used successfully in Python2.5 with matplotlib 0.91.2 and PyQt4 (and Qt 4.3.3)
   2 from distutils.core import setup
   3 import py2exe
   4 
   5 # We need to import the glob module to search for all files.
   6 import glob
   7 
   8 # We need to exclude matplotlib backends not being used by this executable.  You may find
   9 # that you need different excludes to create a working executable with your chosen backend.
  10 # We also need to include include various numerix libraries that the other functions call.
  11 
  12 opts = {
  13     'py2exe': { "includes" : ["sip", "PyQt4._qt", "matplotlib.backends",  "matplotlib.backends.backend_qt4agg",
  14                                "matplotlib.figure","pylab", "numpy", "matplotlib.numerix.fft",
  15                                "matplotlib.numerix.linear_algebra", "matplotlib.numerix.random_array",
  16                                "matplotlib.backends.backend_tkagg"],
  17                 'excludes': ['_gtkagg', '_tkagg', '_agg2', '_cairo', '_cocoaagg',
  18                              '_fltkagg', '_gtk', '_gtkcairo', ],
  19                 'dll_excludes': ['libgdk-win32-2.0-0.dll',
  20                                  'libgobject-2.0-0.dll']
  21               }
  22        }
  23 
  24 # Save matplotlib-data to mpl-data ( It is located in the matplotlib\mpl-data
  25 # folder and the compiled programs will look for it in \mpl-data
  26 # note: using matplotlib.get_mpldata_info
  27 data_files = [(r'mpl-data', glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\*.*')),
  28                     # Because matplotlibrc does not have an extension, glob does not find it (at least I think that's why)
  29                     # So add it manually here:
  30                   (r'mpl-data', [r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']),
  31                   (r'mpl-data\images',glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\images\*.*')),
  32                   (r'mpl-data\fonts',glob.glob(r'C:\Python25\Lib\site-packages\matplotlib\mpl-data\fonts\*.*'))]
  33 
  34 # for console program use 'console = [{"script" : "scriptname.py"}]
  35 setup(windows=[{"script" : "scriptname.py"}], options=opts,   data_files=data_files)

Excluding some backends

If you omit some backends you must make sure it isn't the default - for example if you package WX backend and not Tcl/Tk:

The default backend is configured in mpl-data/matplotlib.conf. You can override the configuration in your program by doing for example:

import matplotlib
matplotlib.use('wxagg') # overrule configuration
import pylab

Updating _sort confusion

If you're using numarray and numpy together, be aware that they both have a _sort, and py2exe gets them confused. After py2exe creates the dist directotry, copy numpy/core/_sort.pyd and numarray/sort.pyd to their respective locations in the dist.

If you get an error that numarray module has no functionDict in numarraycore.py at line 176, then you'll know that py2exe confused the _sort modules that are in both numpy and numarray and need to do this step.

MPL datafiles etc with Python 2.5 and MPL 0.99

Using matplotlib.get_py2exe_datafiles() helps to make this really easy now.

Following is copy/paste from my larger setup.py, but it should work.

   1 from distutils.core import setup
   2 import py2exe
   3 
   4 # my setup.py is based on one generated with gui2exe, so data_files is done a bit differently
   5 data_files = []
   6 
   7 import matplotlib as mpl
   8 data_files += mpl.get_py2exe_datafiles()
   9 
  10 setup(
  11     console=['test.py'],
  12     options={
  13              'py2exe': {
  14                         'packages' : ['pytz', ],
  15                        }
  16             },
  17     data_files=data_files
  18 )

Note that I did not need to define matplotlib in packages and this works for me using the wxAgg backend.

There is one problem outstanding in 0.99 and that has to do with this kind of code: "psd.doc = psd.doc % kwdocd"

It cause a TypeError exception if one uses ""optimize": 2," in ones setup.py.

My work around is to change that type of code to: if psd.doc is not None:

  • psd.doc = psd.doc % kwdocd

else:

  • psd.doc = ""

Reported this to the mpl list, hopefully a better solution is found for this.

MatPlotLib (last edited 2018-10-31 15:57:34 by JimmyRetzlaff)