Python on Electron 框架

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32158738/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 11:07:44  来源:igfitidea点击:

Python on Electron framework

pythonframeworkscross-platformdesktop-applicationelectron

提问by A Junior

I am trying to write a cross-platform desktop app using web technologies (HTML5, CSS, and JS). I took a look at some frameworks and decided to use the Electron framework.

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

I've already done the app in Python, so I want to know if is possible to write cross-platform desktop applications using Python on the Electron framework?

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

采纳答案by bluesummers

It is possible to work with Electron but if you are looking for "webbish" UI capabilities, you can check Flexx- it allows you to code in pure Python but still use the styling and UI flexibility of web development tools.

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

If you insist on going on Electron you should follow the idea of this post.

如果你坚持使用 Electron,你应该遵循这篇文章的想法。

First make sure you have everything installed:

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

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

Now create the directory where you want all the magic to happen and include following files

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

Create your hello.py:

创建您的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)

Create your basic package.json:

创建您的基本package.json

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

Finally create your main.js:

最后创建您的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();
});

Taken from the post itself - are the following notes

摘自帖子本身 - 以下注释

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.

请注意,在 main.js 中,我们为 Python 应用程序生成了一个子进程。然后我们使用无限循环检查服务器是否已启动(好吧,不好的做法!我们实际上应该检查所需的时间并在几秒钟后中断循环)。服务器启动后,我们构建一个实际的电子窗口,指向新的本地网站索引页面。

回答by Ahmed Bouchefra

You can use python-shell to communicate between Python and Node.js/Electron.

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

python-shell provides an easy way to run Python scripts from Node.js with basic and efficient inter-process communication and better error handling.

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

Using python-shell, you can:

使用 python-shell,您可以:

  • spawn Python scripts in a child process;
  • switch between text, JSON and binary modes;
  • use custom parsers and formatters;
  • perform data transfers through stdin and stdout streams;
  • get stack traces when an error is thrown.
  • 在子进程中生成 Python 脚本;
  • 在文本、JSON 和二进制模式之间切换;
  • 使用自定义解析器和格式化程序;
  • 通过标准输入和标准输出流执行数据传输;
  • 抛出错误时获取堆栈跟踪。

In your terminal, make sure you are inside the root folder of your project and run the following command to install python-shell from npm:

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

npm install --save python-shell 

You can then simply run a Python shell using:

然后,您可以使用以下命令简单地运行 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);
});

See more information from this tutorial

查看本教程的更多信息

回答by M Katz

This is an update to the answer by @bluesummers that works for me on Jan 2, 2020.

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

  1. Install Node (https://nodejs.org/en/download/) and python 3.

  2. Install dependencies:

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

  2. 安装依赖:

    pip install Flask
    npm install electron
    npm install request
    npm install request-promise
  1. Create a directory for your project and create the following files in that directory:
  1. 为您的项目创建一个目录并在该目录中创建以下文件:

main.js

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

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

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. From within the project directory, run:
  1. 从项目目录中,运行:
    npm start