56

I want to build html docs using a virtualenv instead of the native environment on my machine.

I've entered the virtualenv but when I run make html I get errors saying the module can't be imported - I know the errors are due to the module being unavailable in my native environment. How can I specify which environment should be used when searching for docs (eg the virtualenv)?

cerberos
  • 7,705
  • 5
  • 41
  • 43

3 Answers3

69

The problem is correctly spotted by Mathijs.

$ which sphinx-build
/usr/local/bin/sphinx-build

I solved this issue installing sphinx itself in the virtual environment.

With the environment activated:

$ source /home/migonzalvar/envs/myenvironment/bin/activate
$ pip install sphinx
$ which sphinx-build
/home/migonzalvar/envs/myenvironment/bin/sphinx-build

It seems neat enough.

migonzalvar
  • 1,645
  • 14
  • 11
  • 7
    This is the cleanest solution by far -- no hacking Makefiles etc. required. Should be the accepted solution, IMHO. – Jeet Mar 24 '14 at 15:10
  • 2
    This isn't going to work if you have created your virtual environment with access to the global packages and you have a global Sphinx installation. – Tarantula Jun 14 '16 at 13:45
  • 3
    a) it didn't work. b) I don't want to pollute a production `requirements.txt` with something as heavy as sphinx. as per Mathijs `make html SPHINXBUILD='python /sphinx-build'` where I got the path from `which sphinx-build`. Now, when I say *didn't work*, might be because sphinx was already in global pip, dunno. So, *this should be accepted* is highly subjective. – JL Peyret Jun 27 '18 at 17:15
  • This works for me and is indeed neat enough. @JLPeyret putting it in your virtual env does not necessarily imply to put it in the `requirements.txt` (I mean it's worth not putting it to be able not to change makefile to make this work) – Romain Aug 01 '19 at 15:15
59

The problem here is that make html uses the sphinx-build command as a normal shell command, which explicitly specifies which Python interpreter to use in the first line of the file (ie. #!/usr/bin/python). If Python gets invoked in this way, it will not use your virtual environment.

A quick and dirty way around this is by explicitly calling the sphinx-build Python script from an interpreter. In the Makefile, this can be achieved by changing SPHINXBUILD to the following:

SPHINXBUILD   = python <absolute_path_to_sphinx-build-file>/sphinx-build

If you do not want to modify your Makefile you can also pass this parameter from the command line, as follows:

make html SPHINXBUILD='python <path_to_sphinx>/sphinx-build'

Now if you execute make build from within your VirtualEnv environment, it should use the Python interpreter from within your environment and you should see Sphinx finding all the goodies it requires.

I am well aware that this is not a neat solution, as a Makefile like this should not assume any specific location for the sphinx-build file, so any suggestions for a more suitable solution are warmly welcomed.

Mathijs
  • 985
  • 9
  • 8
  • 15
    You can use the [shell function](http://www.gnu.org/software/make/manual/make.html#Shell-Function) to avoid hardcoding the absolute path: ``SPHINXBUILD = python $(shell which sphinx-build)`` – ento Mar 16 '11 at 08:18
  • 7
    I'd rather suggest `SPHINXBUILD = python -m sphinx` (as of Sphinx 1.4.5 it is the same), which is more portable across make and avoid a subshell. – bufh Aug 22 '16 at 11:32
  • This answer saved me. Thanks! I just wanted to add that it works fine within `scl` as well, like this: `scl enable python27 'make html SPHINXBUILD=/nfs/tools/lib/python/2.7/current/bin/sphinx-build'` – Philip Durbin Jan 25 '17 at 18:53
  • worked for me too, from within a virtualenv, with a globally installed Sphinx. Txs! – JL Peyret Jun 27 '18 at 17:20
  • @ento and @bufh Both of these solutions leave me with an error saying `No module named 'sphinx'`. Any ideas? – Kajsa Aug 05 '19 at 10:27
  • Thanks so much. This saved the day for me. I activated the venv, and installed sphinx in there, so my command line to build is `make html SPHINXBUILD='../venv/bin/python3.8 ../venv/bin/sphinx-build'`. I was stumped for the whole morning until I found this post. Honestly, how frustrating! None of the Sphinx HOWTO pages mentioned this at all. I'd take you for a beer if it were not for the pandemic. – pauljohn32 Jul 28 '20 at 18:37
  • In other words, if the shebang is fixed in `sphinx-build` to `#!/usr/bin/env python3` the issue goes away... – BlakBat Aug 23 '22 at 21:01
0

I had the same problem, but I couldn't use the accepted solution because I didn't use the Makefile. I was calling sphinx-build from within a custom python build file. What I really wanted to do was to call sphinx-build with the exact same environment that I was calling my python build script with. Fiddling with paths was too complicated and error prone, so I ended up with what seems to me like an elegant solution, which is to "manually" load the console script entry point and call it:

from pkg_resources import load_entry_point
cmd = load_entry_point('Sphinx', 'console_scripts', 'sphinx-build')
cmd(['sphinx-build', basepath, destpath])
Virgil Dupras
  • 2,634
  • 20
  • 22