Search code examples
python-packaging

learning python packaging, the old ModuleNotFoundErrro


What am I doing wrong here???

My structure :-

├── tst
│   ├── setup.py
│   └── tst
│       ├── __init__.py
│       ├── mre.py
│       └── start.py

contents of start.py

from mre import mre


def proc1():
    mre.more()
    return ('ran proc1')


if __name__ == "__main__":
    print('test')
    print(proc1())

contents of mre.py

class mre(object):

    def more():
        print('this is some more')

contents of setup.py

from setuptools import setup

setup(name='tst',
      version='0.1',
      description='just a test',
      author='Mr Test',
      author_email='[email protected]',
      entry_points={'console_scripts': ['tst=tst.start:proc1']},
      license='MIT',
      packages=['tst'],
      zip_safe=False)

nothing in __init__.py

When I run this from the command line all is fine, runs as expected. However when I package this up using PIP and run using tst I get:-

Traceback (most recent call last):
  File "/home/simon/.local/bin/tst", line 5, in <module>
    from tst.start import proc1
  File "/home/simon/.local/lib/python3.8/site-packages/tst/start.py", line 1, in <module>
    from mre import mre
ModuleNotFoundError: No module named 'mre'

I've read numerous posts and I just can't seem to figure this out, if I go into the installed code and change the line

from mre import mre

to

from tst.mre import mre

then it works, but then that doesn't work when running it from the dir for development purposes... I'm obviously missing something obvious :) is it a path issue or am I missing a command in the setup.py?

If someone could point me in the right direction?

edit: do I need to do something different while developing a module thats going to be packaged, perhaps call the code some different way?

cheers


Solution

  • From my point of view, the absolute import from tst.mre import mre is the right thing. You could eventually use from .mre import mre, but the absolute import is safer.

    For development purposes:

    • Use pip's editable mode:
      • path/to/pythonX.Y -m pip install --editable .
      • Similar to setuptools develop mode which is slowly going towards deprecation path/to/pythonX.Y setup.py develop.
    • And run the console script, or the executable module:
      • tst
      • path/to/pythonX.Y -m tst.start

    Without installation, it is often sill possible to run the executable module:

    • path/to/pythonX.Y -m tst.start.