Issue #40 new

Cannot import mpl_toolkits

Anonymous created an issue

I have a project that requires mpl_toolits from matplotlib. mpl_toolkits is not a submodule of matplotlib; it exists in the site-packages directory as it's own module, and is import by itself:

import mpl_toolkits

I have it listed as an included module in the setup function, and I just get an ImportError.

Comments (5)

  1. John David Reaver

    I don't know why mpl_toolkits isn't made into it's own package (with an __init__.py file), but it works with the import statement, and not with cx_Freeze. I have narrowed down the problem to a line in the _FindModule method of ModuleFinder:

    try:
        return imp.find_module(name, path)
    

    According to the Python docs, imp is deprecated and importlibs is supposed to be used from now on. Here is an example of using both to find matplotlib and mpl_toolkits:

    >>> import imp
    >>> import importlib
    >>> imp.find_module('matplotlib')
    (None, '/home/david/Dropbox/.virtualenvs/pyside_test/lib/python3.3/site-packages/matplotlib', ('', '', 5))
    >>> imp.find_module('mpl_toolkits')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/david/Dropbox/.virtualenvs/pyside_test/lib/python3.3/imp.py", line 239, in find_module
        raise ImportError(_bootstrap._ERR_MSG.format(name), name=name)
    ImportError: No module named 'mpl_toolkits'
    >>> importlib.import_module('mpl_toolkits').__path__
    ['/home/david/Dropbox/.virtualenvs/pyside_test/lib/python3.3/site-packages/mpl_toolkits']
    

    Replacing imp with importlib throughout cx_Freeze might take a while and be unnecessary. I am going to try and use importlib if imp fails, and recreate the output of imp.

  2. Thomas Kluyver

    As you've found, there is a way to make it work, but it would be good to make namespace packages work more automatically with cx_Freeze if there's a way to do that. I don't know much about them, though.

  3. John David Reaver

    From what I've read, a namespace package is a package that does not have an __init__ file. Basically, it is a folder that holds other packages:

    site-packages/
      numpy/
        __init__.py
        ....
      mpl_toolkits/
        mplot3d/
          __init__.py
          ...
        ...
    

    As an example, let's consider mpl_toolkits.mplot3d. My plan was to try and find a package in the standard search directories, and if it wasn't found, then append the first part of the package name, in this case mpl_toolkits, to each the search directories, and look for the subpackage mplot3d in the new search directories.

    This shouldn't be hard to do. One way of doing this would be to use the existing namespace_packages functionality, but hide it from the user. If a package isn't found, try to find it as a namespace package, and if that fails say it wasn't found.

    I don't know if there is some subtle error with this approach, but maybe someone who knows more about namespace packages can chime in. I do know that I wasted a couple hours debugging this problem because I did not know what a namespace package was. All I knew was that import mpl_toolkits.mplot3d worked in code, but didn't work in cx_Freeze without the namespace_packages declaration.

  4. Log in to comment