6

I'm having a tough time figuring out how to run NodeJS from Python. I have no problems running ShellScript from Python and NodeJS from ShellScript, but can't seem to get NodeJS from Python, I just get the following output:

b"

These are the simplified version of my scripts.

NodeJS I am trying to run from within Python.

#!/usr/bin/env node
console.log("Hello " + process.argv[2]);

And here is the Python, using Python3.

from datetime import datetime
import json
import os
import re
import sys
import subprocess

if __name__ == '__main__':
        p = subprocess.Popen(['/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)
        out = p.stdout.read()
        print(out)
        

Thanks for the help! Much appreciated.

EDITS: I have no issue executing the following from the commandline, as 'hello.js' is executable:

hello.js 'Brett'

shell=true does not fix it.

Additionally, I am on macOS Catalina 10.15.5 and therefore my shell is zsh.

If I add node to the front of the command, I get no such file or directory for node, I tried it as follows: p = subprocess.Popen(['/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)

9
  • You're reading the wrong argument from argv. If you were calling it like this node hello.js Brett then it would be the third element in argv, but since you used the hashbang and are calling it like a script it would be the second (at index 1) argument. You can see how this fails by calling it without python directly in the shell: cd /Users/Brett/scripts; ./hello.js Brett. Either specify node in the python subprocess call Popen(["node", "/Users/Brett/scripts/hello.js", "Brett"]) or change the index into sys.argv to 1. Commented Jul 12, 2020 at 15:26
  • At least on Linux I don't think that is true. bash $ node ./hello.js Brett Hello Brett [ '/usr/bin/node', '/tmp/so/1/hello.js', 'Brett' ] $ chmod +x hello.js $ ./hello.js Brett Hello Brett [ '/usr/bin/node', '/tmp/so/1/hello.js', 'Brett' ] Commented Jul 12, 2020 at 15:30
  • @MaxStanley hmmm, I'll test it. Given the uppercase Users in the path though I'd assume OP is on MacOS, in which case my fix will definitely work. I'm spinning up a vagrant VM right now to check. Commented Jul 12, 2020 at 15:32
  • you need to run "node /Users/Brett/scripts/hello.js" at least if you want it to run in node enviorment Commented Jul 12, 2020 at 15:35
  • @Talg123 why? OP put a hashbang at the start of the file. Commented Jul 12, 2020 at 15:38

3 Answers 3

8

Thanks everyone for the responses. All were super helpful. Especially @max-stanley and @jared-smith.

The following ended up working for me:

p = subprocess.Popen(['/usr/local/bin/node', '/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)
out = p.stdout.read()
print(out)

Not sure why it doesn't work with the shebang in the executable js file but I am not committed to it, so I will just take the working solution and move on. ;-)

Cheers!

Sign up to request clarification or add additional context in comments.

Comments

3

Okay after doing some testing based on the comments by Max Stanley:

There is an inconsistency between Linux and MacOS here about the population of the argv array. On Mac you will want the second index (1) and on Linux you will want the third (2).

I recommend using a command-line argument parser like command-line-args which should paper over the platform differences.

In the meantime you can specify node in the python subprocess call Popen(["node", "/Users/Brett/scripts/hello.js", "Brett"]) which has the same behavior on both.

5 Comments

Since you have a system where you seem to be able to duplicate what's been posted. Would you mind checking if adding a shell=True to the Popen call fixes things?
shell=True does not fix it. Adding node, gets me no such file or directory for 'node'. I tried it as follows: p = subprocess.Popen(['node', '/Users/Brett/scripts/hello.js', 'Brett'], stdout=subprocess.PIPE)
You an change 'node' to the path where nodejs is installed on your system.
You can use shutil.which() to find node.
@Brett max stanley and paulie4 are correct.
1

Having tested this on my system, it looks as though you need to either make the hello.js file executable chmod +x ./hello.js or you need to add 'node' to the beginning of the Popen argument list as @Jared had said.

5 Comments

Yeah, but if the file isn't executable you'd get an error?
If you didn't add node to the beginning of the Popen argument list yes you would get an error.
So why would adding the executable bit matter if you're specifying the executable?
It wouldn't, I was giving OP the choice, you could either made the .js file executable so that it is run using the environment set in the #! at the top of the file, or you could run the file using node in the Popen argument list, or you could do both,
'hello.js' was already executable. And I can execute it directly from the command line without issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.