Search code examples
pythonnode.jselectronchild-process

Node.js child_process execution of Python script causing errors importing modules


Using child_process.spawn in node.js to execute a python script via an electron app (node.js). If I run the python script on terminal (macOS) there are no problems, but, using node.js and:

const spawn = require('child_process').spawn
let ls = spawn('python', ['runserver.py','--help'], {
  cwd: __dirname,
  detached: true
})

I get errors from python of failed module imports, such as:

Traceback (most recent call last):
  File "runserver.py", line 17, in <module>
    from queue import Queue
ImportError: No module named queue

I've already tried setting different environments with no luck.

Edit:

Here are the logs of sys.path:

  • from code execution via child_process

    [
      '/Users/xAlien95/Desktop/test.app/Contents/Resources/app',
      '/Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
      '/Library/Python/2.7/site-packages',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
      '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC'
    ]
    
  • from code execution via terminal

    [
      '/Users/xAlien95/Desktop/test.app/Contents/Resources/app',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
      '/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
      '/usr/local/lib/python2.7/site-packages',
      '/usr/local/Cellar/protobuf/3.1.0/libexec/lib/python2.7/site-packages'
    ]
    

So, in terminal it's using the homebrew downloaded Python framework. How could I ensure the same will happen in the node.js app?


Solution

  • One way to have python find different libraries is to use the environment variable PYTHONPATH. You can set this in node.js using process.env.PYTHONPATH

    (DOCS) (SOURCE)

    For the specific case of wanting to run the homebrew installed python, the python executable should be available at:

    let ls = spawn(process.env.HOMEBREW_PREFIX + '/bin/python', ['runserver.py','--help'], {
        ...
    

    If HOMEBREW_PREFIX is not available inprocess.env, and the path to the desired python is known, it can be hard-coded into the spawn:

    let ls = spawn(/*<Where my python lives>*/ + '/bin/python', ['runserver.py','--help'], {
        ...