Search code examples
pythonsetuptoolsegg

How to import functions from a submodule in a Python egg?


I have a custom Python egg I've written, which I cannot get the submodule (or nested module) to load externally. I've been able to load a root-level module just fine.

Here's the obfuscated structure:

my_egg/
    my_egg/
        __init__.py (empty file)
        module_one.py
        my_subdir\
            __init__.py (empty file)
            module_two.py
    setup.py

Importing module_one works:

from my_egg import module_one

But I cannot seem to get module_two to import. Here's what I've tried:

from my_egg.my_subdir import module_two
from my_egg import my_subdir.module_two
from my_egg.my_subdir.module_two import *

None of those worked. Here's what my setup.py looks like:

from setuptools import setup

setup(name='my_egg',
  version='0.1',
  packages=['my_egg'],
  test_suite='nose.collector',
  tests_require=['nose'],
  zip_safe=False)

Solution

  • I'm surpised no one answered this. I was able to get it working after scouring Google, pulling from different sources, and trying different things.

    One thing which held me up... I was trying to install my custom egg on a Databricks cluster. And I didn't realize that once you delete a library (egg) the cluster must be restarted in order for it to be deleted. So every time I would try changes, nothing took effect. This definitely delayed my progress.

    In any case, I changed to my setup.py file to use find_packages and made changes to the empty __init__.py files. I'm not really sure if both changes were needed, or if one would've sufficed.

    New my_egg/setup.py:

    exec(open('my_egg/version.py').read())
    
    from setuptools import setup, find_packages
    
    setup(name='my_egg',
          version=__version__,
          packages=find_packages(exclude=('tests', 'docs')),
          test_suite='nose.collector',
          tests_require=['nose'],
          zip_safe=False)
    

    I added a my_egg/version.py file to help me debug if I was using the right version on the cluster. That addition actually led me to discover that Databricks requires the cluster be restarted.

    New root init my_egg/my_egg/__init__.py file:

    from .version import __version__
    from .module_one import module_one_func
    from .my_subdir.module_two import module_two_func
    
    __all__ = ['module_one_func']
    

    New sub-dir init my_egg/my_egg/my_subdir/__init__.py:

    from module_two import module_two_func
    
    __all__ = ['module_two_func']