Archarachne Archarachne - 4 months ago 18
Python Question

Sphinx - file not found - sys.path issue

I am trying to build documentation for my flask project, and I am experiencing issues with the path

My project structure is like:

myproject
config
all.py
__init__.py
logger.py
logger.conf
myproject
models.py
__init__.py
en (english language docs folder)
conf.py


logger.py includes a line

with open('logger.conf') as f: CONFIG = ast.literal_eval(f.read())


which reads the configuration from logger.conf

While "make html"

I receive many errors according to models:

/home/username/projects/fb/myproject/en/models/index.rst:7: WARNING: autodoc: failed to import class u'User' from module u'myproject.models'; the following exception was raised:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/sphinx/ext/autodoc.py", line 326, in import_object
__import__(self.modname)
File "/home/username/projects/fb/myproject/myproject/__init__.py", line 14, in <module>
from logger import flask_debug
File "/home/username/projects/fb/myproject/logger.py", line 5, in <module>
with open('logger.conf') as f: CONFIG = ast.literal_eval(f.read())
IOError: [Errno 2] No such file or directory: 'logger.conf'


which is strange because conf.py includes the path:
sys.path.insert(0, '/home/username/projects/fb/myproject/')

and when I print sys.path it shows that the path is there.

When I paste FULL PATH to the file logger.conf in logger.py it goes to another line simmilar to that and throws the same error for a different file.

Why Sphinx does not check the path files relatively to the sys.path?

Because it does not work for "./file" or "file". It started working only for "../file" - when I changed all the paths, but "destroyed" python working, as for python the path is broken.

Answer

It is the behaviour of open() that is the problem. Commands like open() and chdir() and so work from the directory you're now in, which is probably the directory where the makefile is.

To test it, add an print(os.listdir('.') above your call to open('logger.conf'), that'll show you the problem.

The solution? Use an absolute path. So, a little bit verbose, something like this:

import os

this_directory = os.path.dirname(__file__)
# __file__ is the absolute path to the current python file.
open(os.path.join(this_directory, 'logger.conf'))

Bonus points if you've turned it into a python package (="it has an setup.py"), in that case you can do: 

import pkg_resources

open(pkg_resources.resource_filename('myproject.config', 'logger.conf'))