pyinstall and matplotlib

Russell E. Owen rowen at cesmail.net
Wed Feb 13 13:07:29 EST 2008


In article 
<3144e444-3542-4550-a280-ff15da8bed0b at l16g2000hsh.googlegroups.com>,
 John Henry <john106henry at hotmail.com> wrote:

> On Feb 9, 2:53 pm, John Henry <john106he... at hotmail.com> wrote:
> > Has anybody been able to create an exe of their python applications
> > involving matplotlib using pyinstall (ver 1.3)?  I am getting a:
> >
> >      RuntimeError: Could not find the matplotlib data files
> >
> > when I attempt to run the exe created.
> >
> > In searching the web, it appears this is an issue when others tried to
> > use py2exe as well.  Unfortunately, the few hits I saw doesn't include
> > enough details to inspire me as to what I should be doing in my
> > pyinstall .spec file.
> >
> > Does anybody has an example or information about this?
> >
> > Thanks,
> 
> Well, looks like nobody has an answer to this question.
> 
> How'bout py2exe or other ways of creating exe files out of matplotlib
> projects?  Has anybody been able to do that?  (I am cross-posting
> these messages to the matploblib mailing list).

For py2exe I have appended a setup script I use to bundle an application 
that includes matplotlib. I am no Windows expert and there are probably 
better ways to do it, but it does work. I have made no attempt to strip 
out extra stuff.

(As for pyinstaller:a year or so ago I tried to use it to make a bundled 
*unix* version of my app. If that had worked I'd have considered trying 
to use it for Windows as well. But after a lot of experimenting I was 
never able to get anything even close to functional. Maybe it's better 
now.)

-- Russell

from distutils.core import setup
import os
import sys
import matplotlib
import py2exe

# The following code is necessary for py2exe to find win32com.shell.
# Solution from 
<http://starship.python.net/crew/theller/moin.cgi/WinShell>
import win32com
import py2exe.mf as modulefinder
for pth in win32com.__path__[1:]:
    modulefinder.AddPackagePath("win32com", pth)
for extra in ["win32com.shell"]:
    __import__(extra)
    m = sys.modules[extra]
    for pth in m.__path__[1:]:
        modulefinder.AddPackagePath(extra, pth)

tuiRoot = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
roRoot = os.path.join(tuiRoot, "ROPackage")
sys.path = [tuiRoot, roRoot] + sys.path
import TUI.Version
mainProg = os.path.join(tuiRoot, "runtui.py")

NDataFilesToPrint = 0 # number of data files to print, per directory

def addDataFiles(dataFiles, fromDir, toSubDir=None, 
inclHiddenDirs=False):
    """Find data files and format data for the data_files argument of 
setup.
    
    In/Out:
    - dataFiles: a list to which is appended zero or more of these 
elements:
        [subDir, list of paths to resource files]
    
    Inputs:
    - fromDir: path to root directory of existing resource files
    - toSubDir: relative path to resources in package;
        if omitted then the final dir of fromDir is used
    - inclHiddenDirs: if True, the contents of directories whose names
        start with "." are included
    
    Returns a list of the following elements:
    """
    lenFromDir = len(fromDir)
    if toSubDir == None:
        toSubDir = os.path.split(fromDir)[1]
    for (dirPath, dirNames, fileNames) in os.walk(fromDir):
        if not inclHiddenDirs:
            numNames = len(dirNames)
            for ii in range(numNames-1, -1, -1):
                if dirNames[ii].startswith("."):
                    del(dirNames[ii])
        if not dirPath.startswith(fromDir):
            raise RuntimeError("Cannot deal with %r files; %s does not 
start with %r" %\
                (resBase, dirPath, fromDir))
        toPath = os.path.join(toSubDir, dirPath[lenFromDir+1:])
        filePaths = [os.path.join(dirPath, fileName) for fileName in 
fileNames]
        dataFiles.append((toPath, filePaths))

# Add resources
dataFiles = []
# TUI resources
for resBase in ("Help", "Scripts", "Sounds"):
    toSubDir = os.path.join("TUI", resBase)
    fromDir = os.path.join(tuiRoot, toSubDir)
    addDataFiles(dataFiles, fromDir, toSubDir)
# RO resources
for resBase in ("Bitmaps",):
    toSubDir = os.path.join("RO", resBase)
    fromDir = os.path.join(roRoot, toSubDir)
    addDataFiles(dataFiles, fromDir, toSubDir)
    
# Add tcl snack libraries
pythonDir = os.path.dirname(sys.executable)
snackSubDir = "tcl\\snack2.2"
snackDir = os.path.join(pythonDir, snackSubDir)
addDataFiles(dataFiles, snackDir, snackSubDir)

# Add matplotlib's data files.
matplotlibDataPath = matplotlib.get_data_path()
addDataFiles(dataFiles, matplotlibDataPath, "matplotlibdata")

if NDataFilesToPrint > 0:
    print "\nData files:"
    for pathInfo in dataFiles:
        print pathInfo[0]
        nFiles = len(pathInfo[1])
        for resPath in pathInfo[1][0:NDataFilesToPrint]:
            print "  ", resPath
        if nFiles > NDataFilesToPrint:
            print "  ...and %d more" % (nFiles - NDataFilesToPrint)

versDate = TUI.Version.VersionStr
appVers = versDate.split()[0]
distDir = "TUI_%s_Windows" % (appVers,)

inclModules = [
#    "email.Utils", # needed for Python 2.5.0
]
# packages to include recursively
inclPackages = [
    "TUI",
    "RO",
    "matplotlib",
    "dateutil", # required by matplotlib
    "pytz", # required by matplotlib
#    "matplotlib.backends",
#    "matplotlib.numerix",
#    "encodings",
#    "numpy",
#    "email", # needed for Python 2.5
]

setup(
    options = dict(
        py2exe = dict (
            dll_excludes = [
                # the following are for matplotlib 0.87:
                "libgdk_pixbuf-2.0-0.dll", 
                "libgobject-2.0-0.dll",
                "libgdk-win32-2.0-0.dll",
                "wxmsw26uh_vc.dll",
            ],
            excludes = [ # modules to exclude
                "_gtkagg",
                "_wxagg",
            ],
            #includes = inclModules,
            packages = inclPackages,
        )
    ),
    windows=[ # windows= for no console, console= for console
        dict(
            script = mainProg,
            dest_base = "TUI",
            icon_resources = [(1, "TUI.ico")],
        ),
    ],
    data_files = dataFiles,
)

# rename dist to final directory name
os.rename("dist", distDir)



More information about the Python-list mailing list