Python 关于 Electron 框架

Python on Electron framework

我正在尝试使用网络技术(HTML5、CSS 和 JS)编写跨平台桌面应用程序。我看了一些框架并决定使用 Electron 框架。

我已经在 Python 中完成了该应用程序,所以我想知道是否可以在 Electron 框架上使用 Python 编写跨平台桌面应用程序?

可以使用 Electron,但如果您正在寻找 "webbish" UI 功能,您可以检查 Flexx - 它允许您在纯 Python 但仍然使用 Web 开发工具的样式和 UI 灵活性。

如果你坚持使用 Electron,你应该遵循这个思路 post

首先确保你已经安装了所有的东西:

pip install Flask
npm install electron-prebuilt -
npm install request-promise -g

现在创建您希望所有魔法发生的目录并包含以下文件

创建你的 hello.py:

from __future__ import print_function
import time
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World! This is powered by Python backend."

if __name__ == "__main__":
   print('oh hello')
    #time.sleep(5)
    app.run(host='127.0.0.1', port=5000)

创建你的基本 package.json:

{
  "name"    : "your-app",
  "version" : "0.1.0",
  "main"    : "main.js",
  "dependencies": {
    "request-promise": "*",
    "electron-prebuilt": "*"
  }
}

最终创建您的 main.js:

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

var mainWindow = null;

app.on('window-all-closed', function() {
  //if (process.platform != 'darwin') {
    app.quit();
  //}
});

app.on('ready', function() {
  // call python?
  var subpy = require('child_process').spawn('python', ['./hello.py']);
  //var subpy = require('child_process').spawn('./dist/hello.exe');
  var rq = require('request-promise');
  var mainAddr = 'http://localhost:5000';

  var openWindow = function(){
    mainWindow = new BrowserWindow({width: 800, height: 600});
    // mainWindow.loadURL('file://' + __dirname + '/index.html');
    mainWindow.loadURL('http://localhost:5000');
    mainWindow.webContents.openDevTools();
    mainWindow.on('closed', function() {
      mainWindow = null;
      subpy.kill('SIGINT');
    });
  };

  var startUp = function(){
    rq(mainAddr)
      .then(function(htmlString){
        console.log('server started!');
        openWindow();
      })
      .catch(function(err){
        //console.log('waiting for the server start...');
        startUp();
      });
  };

  // fire!
  startUp();
});

摘自 post 本身 - 以下是注释

Notice that in main.js, we spawn a child process for a Python application. Then we check whether the server has been up or not using unlimited loop (well, bad practice! we should actually check the time required and break the loop after some seconds). After the server has been up, we build an actual electron window pointing to the new local website index page.

您可以使用 python-shell 在 Python 和 Node.js/Electron 之间进行通信。

python-shell 提供了一种从 Node.js 到 运行 Python 脚本的简单方法,具有基本和高效的进程间通信和更好的错误处理.

使用python-shell,您可以:

  • 在子进程中生成 Python 脚本;
  • 在文本、JSON 和二进制模式之间切换;
  • 使用自定义解析器和格式化程序;
  • 通过标准输入和标准输出流执行数据传输;
  • 在抛出错误时获取堆栈跟踪。

在您的终端中,确保您位于项目的根文件夹中,并运行以下命令从 npm 安装 python-shell:

npm install --save python-shell 

然后您可以简单地 运行 a Python shell 使用:

var pyshell =  require('python-shell');

pyshell.run('hello.py',  function  (err, results)  {
 if  (err)  throw err;
 console.log('hello.py finished.');
 console.log('results', results);
});

从这里查看更多信息tutorial

这是对@bluesummers 在 2020 年 1 月 2 日对我有用的答案的更新。

  1. 安装节点(https://nodejs.org/en/download/)和python 3.

  2. 安装依赖:

    pip install Flask
    npm install electron
    npm install request
    npm install request-promise
  1. 为您的项目创建一个目录并在该目录中创建以下文件:

main.js

const electron = require( "electron" );
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
electron.crashReporter.start( { companyName: "my company", submitURL: "https://mycompany.com" } );

var mainWindow = null;

app.on(
    "window-all-closed",
    function()
    {
        // if ( process.platform != "darwin" )
        {
            app.quit();
        }
    }
);

app.on(
    "ready",
    function()
    {
        var subpy = require( "child_process" ).spawn( "python", [ "./hello.py" ] );
        // var subpy = require( "child_process" ).spawn( "./dist/hello.exe" );
        var rp = require( "request-promise" );
        var mainAddr = "http://localhost:5000";

        var OpenWindow = function()
        {
            mainWindow = new BrowserWindow( { width: 800, height: 600 } );
            // mainWindow.loadURL( "file://" + __dirname + "/index.html" );
            mainWindow.loadURL( "http://localhost:5000" );
            mainWindow.webContents.openDevTools();
            mainWindow.on(
                "closed",
                function()
                {
                    mainWindow = null;
                    subpy.kill( "SIGINT" );
                }
            );
        };

        var StartUp = function()
        {
            rp( mainAddr )
            .then(
                function( htmlString )
                {
                    console.log( "server started!" );
                    OpenWindow();
                }
            )
            .catch(
                function( err )
                {
                    console.log( "waiting for the server start..." );
                    // without tail call optimization this is a potential stack overflow
                    StartUp();
                }
            );
        };

        // fire!
        StartUp();
});

package.json

{
    "name": "your-app",
    "version": "0.1.0",
    "main": "main.js",
    "scripts":
    {
        "start": "electron ."
    },
    "dependencies":
    {
        "electron": "*",
        "request": "^2.88.0",
        "request-promise": "^4.2.5"
    }
}

hello.py

from __future__ import print_function
# import time
from flask import Flask

app = Flask( __name__ )

@app.route( "/" )
def hello():
    return "Hello World! This is powered by a Python backend."

if __name__ == "__main__":
    print( "oh hello" )
    #time.sleep(5)
    app.run( host = "127.0.0.1", port = 5000 )
  1. 在项目目录中,运行:
    npm start

使用我正在开发的 electron-django 应用程序我使用 pyinstaller 来编译我的 django 应用程序,然后只生成它的子进程并且它可以工作,请注意 pyinstaller 可能无法识别所有模块或 dist 文件夹。网上有很多关于如何获得填充 .specs 文件和修改 dist 文件夹以添加您可能需要的文件的解决方法的示例。 pyinstaller 通常会告诉你终端出了什么问题。希望对你有帮助