2

After packaging my app for a linux system, the python script for doing some background tasks fails to execute, probably because it is not packaged correctly. I've looked through several threads now, stumbled over ASAR, extraResources etc. but I'm not really getting it to work.

My folder structure is the following

- App.Root
   |-public
   |    -background.html
   |
   |-scripts
        -python.py

This is the content of my background.html:

<script>
const { PythonShell } = require('python-shell');
const { ipcRenderer } = require('electron');
const path = require('path');

let pyshell

ipcRenderer.on('START_PROCESSING', (event, args) => {

    console.log("Loading Python")

    const { data } = args;
    pyshell = new PythonShell(path.join(__dirname, '/../scripts/python.py'), {
        pythonPath: 'python3',
        pythonOptions:['-u'],
        args: [data]
    });

    pyshell.on('message', function (results) {
        ipcRenderer.send('MESSAGE_FROM_BACKGROUND', { message: results });
    });

});

ipcRenderer.on('QUIT_PYTHON', (event, args) => {
    pyshell.kill();
    ipcRenderer.send('CLOSE_BACKGROUND');
});

ipcRenderer.send('BACKGROUND_READY');

I already tried including the scripts folder like this and I think it worked since it appeared in the "dist" folder but dont know where to go from here:

 "extraResources": [
{
    "from": "scripts",
    "to": "scripts"
}

I understand that this is an issue with paths and how electron is packaging the app, but since I`m new to all of this I feel a bit overwhelmed. People posted a bunch of different solutions which weren't working for me, or the problem was never solved.

I'd be glad if somebody who's familiar with packaging electron apps can chime in.

//EDIT:

This is my current build{} config:

    "build": {
    "files": [
      "build/**/*",
      "node_modules/**/*"
    ],
    "asarUnpack":"./scripts/**",
    "extraResources": "./scripts/**",

    "publish": {
      "provider": "github",
      "repo": "test",
      "owner": "Test"
    }
  },

I also changed:

pyshell = new PythonShell(path.join(__dirname, '/../scripts/python.py')

To:

pyshell = new PythonShell(path.join(process.resourcesPath, '/scripts/python.py')

cause it was obivously wrong.

Traxan
  • 45
  • 7

2 Answers2

1

I am also using Python scripts in my Electron application.

i need see your entire build {} config to see better, but i think that the issue is because your asar doesn't include correctly your ./script folder

In my electron-builder config i have this

"asarUnpack": "./scripts/**",
"extraResources": ["./scripts/**", "./scripts/database/**"], //Note that I also include a folder named database inside my ./script folder

With this lines my folder ./scripts is include correctly

EDIT: // My block with a script that loging me in my app:

ipcMain.on(`login`, async (event, args) => {
    let command = ``;

    if (process.platform === `linux`) {
        command = await exec(`./scripts/login ${args.user} ${args.password}`);
    } 
    command.stdout.on(`data`, (data) => {
        // do something when scripts runs

    command.on(`exit`, (code) => {
        console.log(code);
    });
  • I did some further investigation and I’m quiet certain that my code is alright now after I did some changes. When I’m opening the process which executes the python I’m actually printing the resourcesPath now to the console and it points to a .mount file in the /tmp/ folder. When following the path, I’m finding my python script sitting at the correct location. Somehow it doesn’t execute though. The path is correct and the file is there and when I’m in DEV mode everything is running as well. Am I missing something here? – Traxan Aug 29 '22 at 20:01
  • I also added my build config in the original post for you to see. – Traxan Aug 29 '22 at 21:18
  • Why you do the python call like this ? `pyshell = new PythonShell(path.join(process.resourcesPath, '/scripts/python.py')` I do this call and its work: `command = await exec(`./scripts/login ${args.user} ${args.password}`);` note that im using exec library of node (https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback) i use this to pass arguments inside my python script (also i am compiling it into .exe) – Mole de Astoria Aug 30 '22 at 17:36
  • Thank you for your answer, but I’m afraid I’m not getting it 100%. Do you mean that I don’t need to spawn a new python-shell? I’m not converting to exe, my app gets bundled as appimage on Linux and I just want to call the .py script. Would the code in my case look like this then when assigning variables that fit my code?: runScript = await exec(path.join(process.resourcesPath, ‘./scripts/python.py’)); Maybe you can point me to some code snippet so I can see the code in context? Thank you for your help again!! – Traxan Aug 30 '22 at 18:04
  • Yeah sure i can put al block of code (i making .exe mi script becouse im working actually in windows 10 and i asume that my client don't have python installed on his PC for that reason i compile in .exe or .deb o whatever system i need) in your case can be maybe: `runScript = await exec("python3 /scripts/python.py")` like if you run it directly in terminal – Mole de Astoria Aug 30 '22 at 18:52
1

After some more hours of research and troubleshooting I’d like to post my answer here: Because of my own incompetence I missed that python-shell actually has an error output. After activating this I realized that the script was in fact bundled and loaded. However python couldn’t execute because apparently a module that I imported was not installed. Then it hit me.

I changed

pythonPath: 'python3',

To:

pythonPath: 'python',

Now it works. Maybe this will help somebody in the future.

Traxan
  • 45
  • 7