pyinstaller: _libcouchbase module not found after building the executable

846 views Asked by At

I have a simple python script that imports couchbase module on Ubuntu 14.04:

$ cat test.py
from couchbase import Couchbase

print 'module _libcouchbase found'

Running from interpreter works fine:

$ python test.py
module _libcouchbase found

Created an executable:

$ pyinstaller test.py

Running the executable throws an error of unable to import _libcouchbase module:

$ ./dist/test/test
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/subba/cb/build/cb/out00-PYZ.pyz/mycouch", line 28, in <module>
  File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/subba/cb/build/cb/out00-PYZ.pyz/couchbase", line 28, in <module>
  File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/subba/cb/build/cb/out00-PYZ.pyz/couchbase.user_constants", line 21, in <module>
  File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/subba/cb/build/cb/out00-PYZ.pyz/couchbase._bootstrap", line 34, in <module>
  File "/usr/local/lib/python2.7/dist-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/subba/cb/build/cb/out00-PYZ.pyz/couchbase.exceptions", line 18, in <module>
ImportError: No module named _libcouchbase

It seems very mysterious. Thanks for any thoughts on why this happens!

1

There are 1 answers

0
Yoel On BEST ANSWER

Try creating a file called hook-couchbase.py with the following content:

import os
import glob
import itertools

try:
    # PY_EXTENSION_SUFFIXES is unavailable in older versions
    from PyInstaller.hooks.hookutils import PY_EXTENSION_SUFFIXES
except ImportError:
    try:
        from importlib.machinery import EXTENSION_SUFFIXES as PY_EXTENSION_SUFFIXES
    except ImportError:
        import imp
        PY_EXTENSION_SUFFIXES = set([f[0] for f in imp.get_suffixes()
                                     if f[2] == imp.C_EXTENSION])

def hook(mod):
    module_directory = os.path.dirname(mod.__file__)
    bundled = []

    for libname, ext in itertools.product(('libcouchbase', '_libcouchbase'),
                                          PY_EXTENSION_SUFFIXES):
        bundled.extend(glob.glob(os.path.join(module_directory, libname + ext)))

    for f in bundled:
        name = os.path.join('couchbase', os.path.basename(f))
        if hasattr(mod, 'pyinstaller_binaries'):
            mod.pyinstaller_binaries.append((name, f, 'BINARY'))
        else: # mod.pyinstaller_binaries is unavailable in older versions
            mod.binaries.append((name, f, 'BINARY'))

    return mod

When building, supply the path to the directory in which you placed the file as a value to the --additional-hooks-dir argument, as follows:

--additional-hooks-dir=<path_to_directory_of_hook_file>