eFusion 02 октября 2020

? Соединяем Python и Electron/Node.js в приложении для десктопа

На простых примерах рассказываем о возможном способе интеграции Python с Node.js и Electron в современное приложение.

Перевод публикуется с сокращениями, автор оригинала Ahmed Bouchefra.

Что понадобится

***

Это руководство предназначено для разработчиков на Python, которые хотят создавать настольные приложения с графическим интерфейсом. Мы представим Electron – отличный инструмент, использующий современные веб-технологии: HTML, CSS, JavaScript и связанные с ними фреймворки. Мы также расскажем о различных способах подключения Python и Electron, например, child_process, python-shell и сервер HTTP (Flask).

Вам понадобится:

  • знание Python;
  • умение работать с JS, HTML и CSS;
  • навыки установки и использования пакетов Node.js из npm.
Примечание
Если вы не знакомы с Node.js, прочитайте наше руководство для начинающих.

Шаг 1. Настраиваем среду разработки

В этом разделе мы настроим среду разработки для запуска примеров.

Установка Node.js и npm

Существуют различные способы для установки данных инструментов:

  • установочный файл для вашей операционной системы;
  • менеджер пакетов;
  • менеджер NVM (Node Version Manager) для установки и управления версиями Node.js.

Самое простое – зайти на официальный сайт и загрузить установочный файл, а затем выполнить инструкции по установке Node.js и npm в вашей ОС.

Настройка Electron

Разработка на Electron – это, как ни странно, разработка на Node.js. Поскольку Node.js уже должен быть установлен в предыдущем пункте, переходите к настройке, иначе почитайте в официальном хелпе о начальной настройке для разных ОС.

Из директории проекта запустите команду:

        npm install --save-dev electron
    

Процесс установки содержит различные вариации – изучите их в специальном разделе.

Настройка виртуальной среды Python

Чтобы проверить, что в вашей системе установлен Python 3, откройте терминал и выполните следующую команду:

        $ python --version

Python 3.7.0
    

А теперь давайте создадим виртуальную среду.

Создание виртуальной среды

Виртуальная среда позволяет создать окружение для изоляции зависимостей текущего проекта. Это позволит вам избежать конфликтов между пакетами разных версий. В Python 3 для этих целей можно использовать модуль venv. Перейдите в терминал и выполните следующую команду:

        $ python -m venv env
    

Далее необходимо активировать среду с помощью следующей команды:

        $ source env/bin/activate
    

В Windows виртуальную среду можно активировать с помощью сценария Scripts\activate.bat:

        $ env\Scripts\activate.bat
    

Все готово и можно устанавливать пакеты.

Шаг 2. Создаём Node.js-приложение

Начнём с создания папки для проекта и файла package.json внутри нее с помощью следующих команд:

        $ mkdir python-nodejs-example
$ cd python-nodejs-example
$ npm init -y
    

Команда init сгенерирует файл package.json со следующим содержанием:

        {
  "name": "python-nodejs-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
    

Вы можете вручную настроить значения в этом файле на свое усмотрение. Далее создайте внутри рабочей директории два файла: index.html и index.js:

        $ touch index.js 
$ touch index.html
    

Связываем Electron и Python

Каким-то образом нам понадобится связать между собой Electron и Python.

В компьютерных науках inter-process communication или interprocess communication (IPC) относится к механизмам, которые предоставляет ОС, чтобы позволить процессам управлять общими данными. Как правило, приложения могут использовать IPC, классифицированные как клиенты и серверы, где клиент запрашивает данные, а сервер отвечает на запросы.

IPC относится к набору механизмов, поддерживаемых ОС, которые позволяют различным локальным или удаленным процессам взаимодействовать друг с другом. Например, в нашем случае мы хотим разрешить связь между процессами Electron и Python.

Рассмотрим, как этого достичь.

Создание процесса Python с помощью child_process

Node.js предоставляет модуль child_process, позволяющий создавать дочерние процессы.

Давайте используем его, чтобы породить процесс Python и запустить простой скрипт calc.py. Мы будем использовать simplecalculator для выполнения простых вычислений в Python, поэтому, сначала запустим следующую команду для его установки:

        sudo pip install simplecalculator
    

Внутри папки проекта создайте папку py, а внутри создайте файл calc.py:

        $ mkdir py & cd py

$ touch calc.py
    

Откройте calc.py и добавьте следующий код, который выполняет вычисление и выводит результат в стандартный вывод:

        from sys import argv
from calculator.simple import SimpleCalculator

def calc(text):
	
	try:
		c = SimpleCalculator()
		c.run(text)
		return c.log[-1]
	except Exception as e:
		print(e)
		return 0.0

if __name__ == '__main__':
    print(calc(argv[1]))
    

Затем создайте renderer.js и добавьте туда следующий код для создания процесса Python и выполнения скрипта py/calc.py:

        function sendToPython() {
  var python = require('child_process').spawn('python', ['./py/calc.py', input.value]);
  python.stdout.on('data', function (data) {
    console.log("Python response: ", data.toString('utf8'));
    result.textContent = data.toString('utf8');
  });

  python.stderr.on('data', (data) => {
    console.error(`stderr: ${data}`);
  });

  python.on('close', (code) => {
    console.log(`child process exited with code ${code}`);
  });

}

btn.addEventListener('click', () => {
  sendToPython();
});

btn.dispatchEvent(new Event('click'));
    

Затем откройте index.html и обновите его следующим образом:

        <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Calling Python from Electron!</title>
</head>

<body>
    <h1>Simple Python Calculator!</h1>
    <p>Input something like <code>1 + 1</code>.</p>
    <input id="input" value="1 + 1"></input>
    <input id="btn" type="button" value="Send to Python!"></input>
    </br>
    Got <span id="result"></span>
    
    <script src="./renderer.js"></script>

</body>
</html>
    

Использование python-shell

Теперь посмотрим, как использовать python-shell.

Python-shell – это npm-пакет, обеспечивающий простой способ запуска скриптов Python из Node.js с межпроцессным взаимодействием и обработкой ошибок.

Вы можете также использовать python-shell для:

  • порождения скриптов Python;
  • переключения между текстовым, JSON и двоичным режимами;
  • выполнения передачи данных через потоки stdin и stdout;
  • получения трассировок стека в случае возникновения ошибок.

Перейдите в терминал и выполните следующую команду для установки python-shell:

        $ npm install --save python-shell
    

Затем откройте renderer.js и перепишите функцию sendToPython() следующим образом:

        function sendToPython() {
  var { PythonShell } = require('python-shell');

  let options = {
    mode: 'text',
    args: [input.value]
  };

  PythonShell.run('./py/calc.py', options, function (err, results) {
    if (err) throw err;
    // результаты - это массив, состоящий из сообщений, собранных во время выполнения
    console.log('results: ', results);
    result.textContent = results[0];
  });

}
    

Использование связи клиент-сервер

Теперь рассмотрим другой способ создания связи между Python и Electron с помощью сервера HTTP.

В терминале выполните следующую команду для установки Flask и Flask-Cors:

        $ pip install flask

$ pip install Flask-Cors
    

В папке py вашего проекта создайте файл server.py и добавьте следующий код для запуска сервера Flask, который выполняет вычисление и возвращает результат в виде HTTP-ответа:

        import sys
from flask import Flask
from flask_cors import cross_origin
from calculator.simple import SimpleCalculator

def calcOp(text):
	
	try:
		c = SimpleCalculator()
		c.run(text)
		return c.log[-1]
	except Exception as e:
		print(e)
		return 0.0

app = Flask(__name__)

@app.route("/<input>")
@cross_origin()
def calc(input):    
    return calcOp(input)

if __name__ == "__main__":
    app.run(host='127.0.0.1', port=5001)
    

Затем откройте файл renderer.js и добавьте следующий код для создания Python и запуска server.py:

        let input = document.querySelector('#input')
let result = document.querySelector('#result')
let btn = document.querySelector('#btn')

function sendToPython() {
  var { PythonShell } = require('python-shell');

  let options = {
    mode: 'text'
  };
  
  PythonShell.run('./py/server.py', options, function (err, results) {
    if (err) throw err;
    // результаты - это массив, состоящий из сообщений, собранных во время выполнения
    console.log('response: ', results);

  });
}

function onclick(){

  fetch(`http://127.0.0.1:5001/${input.value}`).then((data)=>{      
      return data.text();
      
  }).then((text)=>{
    console.log("data: ", text);
    result.textContent = text;
  }).catch(e=>{
    console.log(e);
  })

}
sendToPython();

btn.addEventListener('click', () => {
  onclick();
});

btn.dispatchEvent(new Event('click'))
    

Резюме

В этом руководстве мы представили Electron для Python-разработчиков, который может быть отличным и простым инструментом для создания GUI с помощью современных веб-технологий, основанных на HTML, CSS и JavaScript. На понятном примере с калькулятором были рассмотрены различные способы подключения Python и Electron: child_process, python-shell и сервер HTTP (Flask).

Источники

РУБРИКИ В СТАТЬЕ

МЕРОПРИЯТИЯ

Комментарии 0

ВАКАНСИИ

Ведущий программист Unity3D
Москва, по итогам собеседования
Программист C++ (Gamedev)
по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

BUG