electron 如何将电子应用程序和Flask服务器打包到一个可执行文件中

wecizke3  于 6个月前  发布在  Electron
关注(0)|答案(1)|浏览(99)

到目前为止(在我的mac上),我已经成功地使用python将我的flask应用程序打包成一个.app文件,并且可以成功地将electron打包成一个.app文件。现在我希望能够将flask可执行文件和electron应用程序打包成一个可执行文件。
我已经尝试了其他一些堆栈溢出帖子的建议,并使用child_process模块来生成flask .app,但这给了我以下错误:

Uncaught Exception:
Error: spawn ../server/dist/server.app ENOENT
    at _errnoException (util.js:1024:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
    at onErrorNT (internal/child_process.js:372:16)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

字符串
以下是导致此错误的电子入口点代码:

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

const isDev = require('electron-is-dev');
const path = require('path');
const childSpawn = require('child_process').spawn;

let mainWindow;

const createWindow = () => {
  childSpawn('../server/dist/server.app');

  mainWindow = new BrowserWindow({ width: 900, height: 680 });
  mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`);

  app.setAboutPanelOptions({
    applicationName: 'app_name',
    applicationVersion: '0.0.1',
  })

  mainWindow.on('closed', () => mainWindow = null);
}

app.on('ready', createWindow);

app.on('window-all-closed', () => {
  app.quit(); 
});

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow();
  }
});


然而,如果这是工作,我不知道我怎么能捆绑flask服务器一起电子应用程序到一个可执行文件?
我会感谢一些帮助的人谁已经成功地做到了这一点。

j0pj023g

j0pj023g1#

打包的flask.app是一个可执行文件,它不能作为子进程生成。你必须使用execFile来执行该文件。我引用了this以下是我从该网站引用的片段。

Package

有些人要求打包。这很容易:应用如何打包Python应用程序和Electron应用程序的知识。

Python部件

正在使用PyInstaller。
在终端中运行以下命令:

pyinstaller pycalc/api.py --distpath pycalcdist

rm -rf build/
rm -rf api.spec

字符串
如果一切顺利的话,pycalcdist/API/文件夹应该会显示出来,以及该文件夹中的可执行文件,这是一个完整的独立Python可执行文件,可以移动到其他地方。
请注意:必须生成独立的Python可执行文件!因为我们要分发的目标机器可能没有正确的Python shell和/或所需的Python库。仅仅复制Python源代码几乎是不可能的。

Node. js/电子部件

由于Python可执行文件的原因,这是一个棘手的问题。
在上面的示例代码中,我写了

// part of main.js
  let script = path.join(__dirname, 'pycalc', 'api.py')
  pyProc = require('child_process').spawn('python', [script, port])

然而,一旦我们打包了Python代码,我们就不应该再生成Python脚本了,而应该对生成的可执行文件执行execFile。

Electron没有提供函数来检查应用程序是否在分发中(至少我没有找到),所以我在这里使用了一个变通方法:检查Python可执行文件是否已经生成。
在main.js中,添加以下函数:

// main.js

const PY_DIST_FOLDER = 'pycalcdist'
const PY_FOLDER = 'pycalc'
const PY_MODULE = 'api' // without .py suffix

const guessPackaged = () => {
  const fullPath = path.join(__dirname, PY_DIST_FOLDER)
  return require('fs').existsSync(fullPath)
}

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)
}


然后将函数createPyProc更改为:

// main.js
// the improved version
const createPyProc = () => {
  let script = getScriptPath()
  let port = '' + selectPort()

  if (guessPackaged()) {
    pyProc = require('child_process').execFile(script, [port])
  } else {
    pyProc = require('child_process').spawn('python', [script, port])
  }

  if (pyProc != null) {
    //console.log(pyProc)
    console.log('child process success on port ' + port)
  }
}


关键是,检查 *dist文件夹是否已经生成,如果已经生成,说明我们是在“生产”模式下,execFile直接执行可执行文件;否则,使用Python shell生成脚本。

相关问题