Search code examples
pythonpython-sphinxread-the-docsautodoc

ReadTheDocs Import Error from __init__.py


I am having trouble with readthedocs autodocs - the build completes but my documentation is empty for each class.

Looking at the build information, seem to be getting a Syntax Error which causes a few warning:

print(clean_sample, file=open(new_fname, 'w'))

However, this does not seem like a bug to me at all.

Here is the build information https://readthedocs.org/projects/medembed/builds/7108142/

My file structure is:

MedEmbed/
  docs/
    build/
    source/
      code.rst
      conf.py
      index.rst
  medembed/
    __init.py
    main.py
    transformer.py
    dataset.py
    embedding.py

As such I added within conf.py:

sys.path.insert(0, os.path.abspath('../../medembed'))

I could really appreciate some advice please

EDIT: Python3 Sphinx solved the above.

Now, I am importing a constant DIR_PROCESSED from init.py

For some reason Sphinx does not like this:

from medembed import DIR_PROCESSED
ImportError: No module named 'medembed

The build failed: https://readthedocs.org/projects/medembed/builds/7108602/


Solution

  • There were multiple things that were not working correctly with Sphinx.

    • code.rst: you should indicate the package name for every module you want to run autodoc on:

      .. automodule:: medembed.main
         :members:
      
      .. automodule:: medembed.dataset
         :members:
      
      .. automodule:: medembed.embedding
         :members:
      
      .. automodule:: medembed.transformer
         :members:
      
    • conf.py: the path you want to add to SYSPATH is the path to the package's parent directory, not the package itself:

      sys.path.insert(0, os.path.abspath('../../'))
      
    • main.py, dataset.py, embedding.py, transformer.py: you should use relative imports instead of absolute ones, when importing stuff from within your package:

      -from transformer import Transformer
      +from .transformer import Transformer
      
      -from medembed import DIR_PROCESSED
      +from . import DIR_PROCESSED
      
      -from dataset import TxtDataset, XMLDataset
      -from embedding import Embedding
      +from .dataset import TxtDataset, XMLDataset
      +from .embedding import Embedding
      
    • main.py: don't add if __name__ == "__main__" directive: the code would be executed when analyzed by Sphinx, and this is not what you want (see this post). In fact, sphinx forbids this and returns a warning if you try:

      WARNING: autodoc: failed to import module 'medembed.main'; the module executes module level statement and it might call sys.exit().
      

      What you should do instead is create a main.py in the parent directory that won't be analyzed by sphinx:

      from medembed.main import main
      
      if __name__ == '__main__':
          main()
      

      I'm using an absolute import here as this main.py file is not in the medembed package.

    I created a pull request on your repo with all these changes: https://github.com/isaacsultan/MedEmbed/pull/4