Skip to content

Instantly share code, notes, and snippets.

@abulka
Created December 7, 2018 04:49
Show Gist options
  • Save abulka/04e9ec68f3a782b044c7f6f9af3bd0c4 to your computer and use it in GitHub Desktop.
Save abulka/04e9ec68f3a782b044c7f6f9af3bd0c4 to your computer and use it in GitHub Desktop.
bootstrapping code for launching python from electron when packaged inside pyinstaller directory structure
import { app, BrowserWindow, Menu, MenuItem, globalShortcut } from 'electron';
const {ipcMain} = require('electron'); // do not use ipcRenderer in main process, use ipcMain
const path = require('path')
const url = require('url')
const log = require('electron-log'); // https://www.npmjs.com/package/electron-log
const sh = require("shelljs"); // https://github.com/shelljs/shelljs
log.transports.file.level = 'debug'; // transports: console and file, levels: error, warn, info, verbose, debug, silly
log.transports.console.level = 'warn';
log.debug('--------------------- APP START -------------------------------')
log.debug('index.js main process')
log.debug('cwd is', sh.pwd().stdout);
// DEPLOYMENT SUPPORT
const PY_DIST_FOLDER = '../dist' // now lives above
const PY_FOLDER = '..'
const PY_MODULE = 'api_pythermal' // without .py suffix
const guessPackaged = () => {
const fullPath = path.join(__dirname, PY_DIST_FOLDER)
// console.log('looking for dist directory here', fullPath)
// log.info('looking for dist directory here', fullPath)
return require('fs').existsSync(fullPath)
}
const createPyProc = () => {
let script = getScriptPath()
let port = '' + selectPort()
// console.log('script', script, 'port', port, 'guessPackaged', guessPackaged())
log.debug('script', script, 'port', port, 'guessPackaged', guessPackaged())
// enhancement to provide Python with critical env vars
let extra_env = {
NODE_ENV: 'production',
LANG: 'en_AU.UTF-8',
PYTHONUNBUFFERED: '1',
PYTHONDONTWRITEBYTECODE: '1',
EXAMPLE_VAR: 'hey there'
}
// makes a copy of existing env, such that it is, and adds to it
let options = {
env : Object.assign({}, process.env, extra_env),
cwd: sh.pwd().stdout
}
if (guessPackaged()) {
pyProc = require('child_process').execFile(script, [port], options)
}
else {
delete options.NODE_ENV; // don't want in production
let python_path = sh.which('python').stdout // this will return null if no python found
log.debug('which virtual python', python_path)
pyProc = require('child_process').spawn(python_path, [script, port], options)
}
if (pyProc != null) {
// console.log('child process success on port ' + port)
log.debug('child process success on port ' + port)
}
pyProc.stdout.on('data', function (data) {
// console.log('stdout: ' + data.toString());
log.debug('stdout: ' + data.toString().trim());
});
pyProc.stderr.on('data', function (data) {
// console.log('stderr: ' + data.toString());
log.debug('stderr: ' + data.toString().trim());
});
pyProc.on('exit', function (code) {
if (code == null)
log.debug('python exited with null code - WTF?')
else {
// console.log('child process exited with code ' + code.toString());
log.debug('child process exited with code ' + code.toString());
}
python_is_dead = true // just in case need to send before main render windows set up
if (mainWindow == null)
log.debug('Cannot send a message to renderer window that python has exited')
else
mainWindow.webContents.send('python_exited_notice') // for all other cases
});
}
const exitPyProc = () => {
pyProc.kill()
pyProc = null
pyPort = null
}
app.on('ready', createPyProc)
app.on('will-quit', exitPyProc)
const getScriptPath = () => {
if (!guessPackaged()) {
return path.join(__dirname, PY_FOLDER, PY_MODULE + '.py')
}
if (process.platform === 'win32') {
return path.join(__dirname, PY_DIST_FOLDER, PY_MODULE, PY_MODULE + '.exe')
}
return path.join(__dirname, PY_DIST_FOLDER, PY_MODULE, PY_MODULE)
}
// ....
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment