Error: spawn ENAMETOOLONG when trying to send a long string from nodejs to python script

Viewed 1604

I am trying to write some code that will take an image that is uploaded by a user and resize it. The code below works for very small images, but when I try a larger image I receive the error spawn ENAMETOOLONG. I believe this is because the base64 string is much larger. What could I do to send the base64 string to my python script regardless of length ?

server.js

  const _arrayBufferToBase64 = (buffer)  => {
      return Buffer.from(buffer).toString('base64');
  };

  // spawn new child process to call the python script
  const python = spawn('python', ['./python/image_handler.py', _arrayBufferToBase64(imgData), filename]);

  // collect data from script
  python.stdout.on('data', function (pydata) {
    console.log('Pipe data from python script ...');
    });


  python.on('close', (code) => {
    console.log(`child process close all stdio with code ${code}`);
  });

image_handler.py

img_b64 = sys.argv[1]
img_bytes = base64.b64decode(img_b64)  # im_bytes is a binary image
img_file = io.BytesIO(img_bytes)  # convert image to file-like object
img = Image.open(img_file)   # img is now PIL Image object
img.thumbnail((300, 300))# resize image
img.save(sys.argv[2])  # Save Path

print('Finished')
sys.stdout.flush()
1 Answers

You are trying to pass your string as an argument to python which exceeds the limit of standard input. The best way I found for a similar issue like this was to use python-shell.

You can send your base64 string (or any large data) through stdin in the following manner: (Referred from python-shell's documentation about Exchanging data between Node and Python)

import {PythonShell} from 'python-shell';
let pyshell = new PythonShell('my_script.py', { mode: 'text' });

// sends a message to the Python script via stdin
pyshell.send('hello');

pyshell.on('message', function (message) {
  // received a message sent from the Python script (a simple "print" statement)
  console.log(message);
});

// end the input stream and allow the process to exit
pyshell.end(function (err,code,signal) {
  if (err) throw err;
  console.log('The exit code was: ' + code);
  console.log('The exit signal was: ' + signal);
  console.log('finished');
});

While initializing pyshell, you can try using text mode which sends and receives the data as simple string or binary mode which sends and receives the data as is.

On the python side, in your image_handler.py, read it like this:

~
img_b64 = input()
~

Hope this helps anyone who stumbles upon here through Google like me.

Related