1

I'm writing a Python package that does GPU computing using the PyCUDA library. PyCUDA needs to initialize a GPU device (usually by importing pycuda.autoinit) before any of its submodules can be imported.

In my own modules I import whatever submodules and functions I need from PyCUDA, which means that my own modules are not importable without first initializing PyCUDA. That's fine mostly, because my package does nothing useful without a GPU present. However, now I want to write documentation and Sphinx Autodoc needs to import my package to read the docstrings. It works fine if I put import pycuda.autoinit into docs/conf.py, but I would like for the documentation to be buildable on machines that don't have an NVIDIA GPU such as my own laptop or readthedocs.org.

What's the most elegant way to defer the of import my dependencies such that I can import my own submodules on machines that don't have all the dependencies installed?

mzjn
  • 48,958
  • 13
  • 128
  • 248
oceanhug
  • 1,352
  • 1
  • 11
  • 24
  • Which mechanism are you using to process your docstrings? `.. automodule:: mymodule` with `:members:` underneath it? – abarnert Nov 26 '13 at 01:48
  • Yes, for example. Basically, I'm looking for the best way to make all my own modules/classes/functions importable while deferring the import of all modules referring to the GPU until runtime. – oceanhug Nov 26 '13 at 01:56
  • Mocking, perhaps? http://stackoverflow.com/a/15912502/407651, http://stackoverflow.com/a/17369696/407651. – mzjn Nov 26 '13 at 18:13
  • That's what I needed, actually. You should post this as an answer. – oceanhug Nov 26 '13 at 21:39

2 Answers2

1

The usual method I've seen is to have a module-level function like foo.init() that sets up the GPU/display/whatever that you need at runtime but don't want automatically initialized on import.

You might also consider exposing initialization options here: what if I have 2 CUDA-capable GPUs, but only want to use one of them?

Colin Valliant
  • 1,899
  • 1
  • 13
  • 20
1

The autodoc mechanism requires that all modules to be documented are importable. When this requirement is a problem, mocking (replacing parts of the system with mock objects) can be a solution.

Here is an article that explains how mock objects can be used when working with Sphinx: http://blog.rtwilson.com/how-to-make-your-sphinx-documentation-compile-with-readthedocs-when-youre-using-numpy-and-scipy/.

The gist of the article is that it should work if you add something like this to conf.py:

import mock   # See http://www.voidspace.org.uk/python/mock/

MOCK_MODULES = ['module1', 'module2', ...]
for mod_name in MOCK_MODULES:
    sys.modules[mod_name] = mock.Mock()
mzjn
  • 48,958
  • 13
  • 128
  • 248