2

I have a python package that I can use standalone just fine. When I install it to site-packages with pip, though, I lose the ability to import submodules.

My package looks like this:

mypackage
    mypackage
        __init__.py
        mymodule.py
        moduledir
            __init__.py
            mysubmodule.py
    setup.py

If I have the package on my pythonpath, I can use it just fine. But then when I use pip to install it to site-packages, I can't import submodules.

from mypackage import mymodule              # works fine
from mypackage.moduledir import mysubmodule # ModuleNotFoundError: No module named when installed to site-packages, works fine when on pythonpath

What's going on here? How do I change it so that I can import submodules?

Also, I'm sure this is answered somewhere, but I can't find it for the life of me on google or SO. I apologize if its trivial and I'm just googling the wrong terms.

Edit: Here is my setup.py as requested.

from setuptools import setup

setup(name='mypackage',
      version='0.1',
      description='mypackage',
      url='https://gitlab.com/ericksonla/mypackage',
      author='ericksonla',
      author_email='[email protected]',
      license='',
      packages=['mypackage'],
      install_requires=[],
      zip_safe=False)
6
  • 2
    mypackage.moduledir doesn't contain an __init__.py, so it's not a module. Commented Feb 28, 2018 at 21:19
  • Oops, just forgot to include it. It is in my actual package, just failed to type it in here. I updated the question. Commented Feb 28, 2018 at 21:32
  • We'll need to see contents of your setup.py file. Is the distribution on PyPI? Commented Feb 28, 2018 at 21:47
  • I added the setup.py to the question. Its more or less just the example version. The distribution is proprietary so its not on PyPI. Commented Feb 28, 2018 at 21:50
  • When you install the package, is it installing the top level mypackage folder, or the inner one (that contains moduledir)? The nested folders with the same name might be confusing things if the wrong one is getting installed in the wrong place. Commented Feb 28, 2018 at 21:53

2 Answers 2

2

I needed to add the submodules to the packages list in setup.py:

# setup.py
from setuptools import setup

setup(name='mypackage',
      version='0.1',
      description='mypackage',
      url='https://gitlab.com/ericksonla/mypackage',
      author='ericksonla',
      author_email='[email protected]',
      license='',
      packages=[
        'mypackage', 
        'mypackage.moduledir'],
      install_requires=[],
      zip_safe=False)

I'm still not quite sure why I need to import one level down, but not any further.

Sign up to request clarification or add additional context in comments.

Comments

1

I'm glad to see you found a setuptools solution that works for you. An alternative within setuptools that I recently learned about is the setuptools.find_packages() function. With the correct arguments, setuptools.find_packages() can discover and add an arbitrary number of submodules of your package, which folks may find useful for packages that grow in size and add submodules.

If you were to use this method in this example, your setup.py file might look like:

# setup.py
from setuptools import setup, find_packages

setup(name='mypackage',
      version='0.1',
      description='mypackage',
      url='https://gitlab.com/ericksonla/mypackage',
      author='ericksonla',
      author_email='[email protected]',
      license='',
      packages=find_packages(),
      install_requires=[],
      zip_safe=False)

That flexibility comes with some caveats for more complicated use-cases, however.

For example, your current package structure gives your source code module the same name as the package itself (the code for mypackage is stored in directory mypackage). If you were to use a different directory structure, such as

mypackage
    src
        mypackage
            __init__.py
            mymodule.py
            moduledir
                __init__.py
                mysubmodule.py
    tests
        mytest.py
    setup.py

where the source code is in the src subdirectory, I think you would need to specify the "where" argument of find_packages in your setup.py file and add the package_dir argument to tell setuptools.setup() that it should map the contents of src to your package name, not to a src submodule:

# setup.py
from setuptools import setup, find_packages

setup(name='mypackage',
      version='0.1',
      description='mypackage',
      url='https://gitlab.com/ericksonla/mypackage',
      author='ericksonla',
      author_email='[email protected]',
      license='',
      packages=find_packages('src'),
      package_dir={'': 'src'}
      install_requires=[],
      zip_safe=False)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.