1

I have a web app built using node and express that uses a python script to generate an excel file. The issue is that although node is successfully handling the request to create the excel file, the handler is also trying to download the file just created but is giving the error: Error: ENOENT: no such file or directory. I'm assuming this is because it is trying to access the file before it is created but I thought that by using await the file would be created first. Here is my code:

Routes:

router.post('/executepythonscript', db.executePythonScript)

Handler:

const executePythonScript = async (request, response) => {
    const { spawn } = require('child_process');

    let pythonPromise = new Promise((resolve, reject) => {
        const python = spawn('py', ['./scripts/generate_excel.py', request.body.week]);
        
        python.stdout.on("data", (data) => {
            resolve(data.toString());
        });
        python.stderr.on("data", (data) => {
            reject(data.toString());
        });
        python.on('close', (code) => {
            console.log(`child process exited with code ${code}`);
        });
    });

    try {
        await pythonPromise;
    } catch (error) {
        console.log(error);
    }

    response.download('[myPath]/timetracking.xlsx');
}

Am I using await wrong or why would the program try to open the file before it is created?

NicLovin
  • 317
  • 3
  • 20
  • [Possibly this promise based approach might be worth a look](https://stackoverflow.com/questions/30763496/how-to-promisify-nodes-child-process-exec-and-child-process-execfile-functions) – Peter White Nov 15 '21 at 18:53
  • Could you not just use `.then( response.download('...') )` instead? And shouldn't you wait on the `resolve` until you get the `on close`? Just because you get something on stdout does not necessarily mean the task is complete. If the Python code is lazy about closing files, it might not happen until shutdown. – Tim Roberts Nov 15 '21 at 18:54
  • @TimRoberts I have tried using ```.then(...)``` with the same results – NicLovin Nov 15 '21 at 19:24

1 Answers1

2

Get rid of the try / catch statement in the function and add the response.download() to python.on(close). It should look like this:

const { spawn } = require('child_process');

const python = spawn('py', ['./scripts/generate_excel.py', request.body.week]);
python.stderr.on("data", (data) => {
   console.log(data.toString());
});
python.on('close', (code) => {
   console.log(`child process exited with code ${code}`);
   response.download('[Path]/tracking/timetracking.xlsx');
});
Tyler2P
  • 2,324
  • 26
  • 22
  • 31