vaid
vaid

Reputation: 1540

Running Conda commands in NodeJS

I can't run a Conda command using exec with my NodeJS app.

var conda_path = '~/miniconda3/bin/conda'

var cmd = conda_path + ' init bash & ' + conda_path + ' activate XYZ'
exec(command,
    function(error, stdout, stderr){

    }
);

I get the following error:

/bin/sh: /Users/username/Desktop/repos/project/XYZ: is a directory

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'. To initialize your shell, run

$ conda init <SHELL_NAME>

Currently supported shells are: - bash - fish - tcsh - xonsh - zsh - powershell

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.

I can find no related information online regarding running conda commands from NodeJS app.

How can I make this work?

Upvotes: 2

Views: 2763

Answers (2)

vaid
vaid

Reputation: 1540

t seems to work using the & character to run multiple commands.

I also needed to specify the path to conda.sh which resides inside /users/username/miniconda??/etc/profile.d/.

This file can be copied to any location, e.g your NodeJS app's root folder.

Here's the working code:

Windows 10

var commands = [
        'C:\\anaconda\\Scripts\\activate.bat C:\\anaconda',
        'conda activate XYZ_v0_1_env',
        'XYZ arg1  <some_file_input> arg2 arg3 arg4 <some_file_output>',
    ]

exec(commands.join(' & '),
    function(error, stdout, stderr){
        console.log(error)
        console.log(stdout)
        console.log(stderr)
    }
);

OSX

const exec = require('child_process').exec;

var conda_path = __dirname + '/conda.sh'

var commands = [
        conda_path,
        conda_path + ' init',
        conda_path + ' activate XYZ_v0_1_env',
        'XYZ arg1  <some_file_input> arg2 arg3 arg4 <some_file_output>',
    ]

exec(commands.join(' & '),
    function(error, stdout, stderr){
        console.log(error)
        console.log(stdout)
        console.log(stderr)
    }
);

EDIT: Using spawn instead of exec to read the live output of the process, i.e to generate live progress:

var commands = [
        'C:\\anaconda\\Scripts\\activate.bat C:\\anaconda',
        'conda activate XYZ_v0_1_env',
        'XYZ arg1  <some_file_input> arg2 arg3 arg4 <some_file_output>',
    ]

var spawn_ = spawn(commands.join('&'), { shell: true });

spawn_.stdout.on('data', function (data) {
    //do something
});

spawn_.stderr.on('data', function (data) {
    //do something
});

spawn_.on('exit', function (code) {
    //do something
});

Upvotes: 1

merv
merv

Reputation: 76750

conda run

Conda provides the conda run command for executing programs or running scripts inside an environment without having to manually activate it. In your case, you only need one command then, e.g.,

var conda_exec = "C:\\anaconda\\Scripts\\conda.exe"
var env_name = "XYZ"
var sub_cmd = "XYZ arg1 <some_file_input> arg2 arg3 arg4 <some_file_output>"

var command = [conda_exec, 'run', '-n', env_name, sub_cmd].join(" ")

...

Be aware that conda run currently does not return I/O results until the very end. This means you won't be able to measure progress of the executing command, and also that you shouldn't use this if you expect a large return (i.e., won't fit in memory).


Suggestion: Consider naming the env XYZ_env or even include versioning (e.g., XYZ_v0_1_env), so you distinguish between XYZ the env and XYZ the program.

Upvotes: 3

Related Questions