pythonpython-importpython-sphinxautodoc

Sphinx cannot find module during make html, but parent folder of package is on path


Note: edited to reflect name change from gui.py to neuro_gui.py

Here is my project structure:

gui
├── src
│   └── gui
│       ├── __init__.py
│       ├── neuro_gui.py
│       └── listen.py
└── docs
    ├── _build
    ├── conf.py
    └── etc

In my conf.py I do:

import os 
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath('../src/'))
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
napoleon_google_docstring = False

In the root gui directory, I do the command: sphinx-apidoc -o docs src\gui src\gui\ui_*

This generates a gui.rst and modules.rst in docs.

Then I do make html in the docs directory. Here sphinx properly creates documentation for listen.py. But in neuro_gui.py, I have the following import: from listen import Listener

This is causing issues; Sphinx says

WARNING: autodoc: failed to import module 'gui' from module 'gui'; the following exception was raised: No module named 'listen'

I tried doing relative imports (i.e. from .listen import listener) and this fixed the issue with sphinx, however it broke the script itself. I also tried adding from __future__ import absolute_import to my __init__.py and using absolute imports, but this resulted in the same behavior (i.e. docs generate fine but script breaks).

To be more specific, as suggested in a comment: it says 'ModuleNotFoundError: No module named 'gui' if I do from gui.listen import listener and ImportError: attempted relative import with no known parent package with from .listen import listener Both of these changes cause Sphinx to work properly but break the script

I have also discovered that the sys.path.insert(0, os.path.abspath('..')) in conf.py has no effect, I only need the sys.path.insert(0, os.path.abspath('../src/')) line.

Would appreciate any input; I am pretty inexperienced with Sphinx and I have tried the suggestions from many other threads re: this issue, but none worked so far


Solution

  • I solved this by changing my __init__.py to:

    import sys
    import os
    sys.path.append(os.path.abspath(''))
    import gui.listen
    import gui.neuro_gui
    

    Then in all my source files I used relative imports.

    Following that, instead of running the source files directly I import their contents into a main.py at the src directory, and run the program there. Sphinx is able to document the code and I am able to run it properly. The fact that Python makes it very difficult to run classes/code from a module in the same module is irritating and probably my least favorite feature of the language!