使用Bootstrap和PyWebView创建UI,并使用PyInstaller使其成为EXE


使用PyWebView加载现有的HTML和CSS,PyWebView是使用HTML构建Python GUI的库。此外,我将使用PyInstaller对其进行打包,以便可以将其用作EXE。

准备什么

  • Windows 10 1903版本
  • Python 3.7.5
  • PyInstaller 3.7
  • PyWebView 3.0.2
  • pipenv 2018.10.13
  • Bootstrap(这次使用Bootstrap-honoka 4.1.3)

由于打包的原因,pipenv放置在项目文件夹中很方便,因此请预先在环境变量中设置PIPENV_VENV_IN_PROJECT=true

工作

安装所需的库

暂时开始工作。创建一个适当的文件夹,并使用pipenv安装PyInstaller和PyWebView。

1
2
3
4
5
mkdir pywebtest
cd pywebtest
pipenv install --python C:\Python36\Python.exe
pipenv install pywebview
pipenv install --dev pyinstaller

接下来,创建所需的最少文件夹

1
2
mkdir html
mkdir src

引导程序

简介

接下来,安装Bootstrap。这次,我将使用npm

介绍该库。

1
2
3
npm init
... // パッケージの設定は適当で良いです
npm install --save bootstrap-honoka

为GUI

创建一组HTML

html文件夹中创建以下三个文件。

  • html / main.html
  • html / main.css
  • html / main.js

html / main.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  Test
</head>
<body>
<h1>It works!</h1>
<button class="btn btn-primary">test button</button>
</body>
</html>

html / main.css

1
2
3
4
5
6
body{
  padding: 12px;
}
h1::after{
  content: " with CSS";
}

html / main.js

1
2
3
document.querySelector("button").addEventListener("click", function(){
  alert("It works!");
});

到目前为止,我认为它类似于以下内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pywebtest
│  package-lock.json
│  package.json
│  Pipfile
│  Pipfile.lock
│  
├─.venv
│      
├─html
│      main.css
│      main.html
│      main.js
│       
├─node_modules
│  └─bootstrap-honoka
└─src
        ここにソースファイル

为GUI调用编写代码

现在,让我们编写用于创建GUI的代码。有两点需要注意

  • 当PyWebView显示一个窗口时,它将占用该线程(如果要进行后续处理,则需要创建一个线程)
  • PyWebView没有加载HTML或CSS文件的方法,因此您需要使load_html,load_css和valuate_js方法加载打开的文件。

以上特别重要。我将阅读以下内容。

src / main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import webview

def load_css(path):
  with open(path, mode="r", encoding="utf-8") as f:
    webview.load_css(f.read())

def load_js(path):
  with open(path, mode="r", encoding="utf-8") as f:
    webview.evaluate_js(f.read())

def load_thread():
  load_html("html/main.html")
  load_css("html/main.css")
  load_css("node_modules/bootstrap-honoka/dist/css/bootstrap.min.css")
  load_js("html/main.js")

with open(path, mode="r", encoding="utf-8") as f:
  html = f.read()
window = webview.create_window(title="Test Application", html=html, width=640, height=320)
webview.start(load_thread, window)

完成此操作后,使用pipenv run运行它。

1
pipenv run ./src/main.py

然后,该应用将暂时启动,并且将在成功加载Bootstrap的情况下显示HTML。
image.png

另外,如果在load_css之后调用一个load_html,则似乎加快了处理速度,但是如果这样做,它将在GUI显示阶段陷入无限循环,因此将无法工作...确保在加载CSS之前先加载HTML。

使用PyInstaller创建可执行文件

然后,我将尝试使用PyInstaller。和以前一样,编写用于构建的PowerShell脚本。

create_exe.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ディレクトリの用意
if (Test-Path dist) {
  Remove-Item dist -Recurse | Out-Null
}
New-Item dist -ItemType Directory | Out-Null
# windllを捜索
Write-Host "> Searching WinDLL"
$windll = "c:\windows\WinSxS\x86_microsoft-windows-m..namespace-downlevel_*"
$windllpath = "."
if(Test-Path $windll){
  $item = (Get-ChildItem $windll | Sort-Object LastWriteTime)[0]
  $windllpath = '"c:\windows\WinSxS\{0}"' -f $item.Name
}
# pyinstaller
Write-Host "> Creation EXE"
pyinstaller `
  --name TestAPP `
  --windowed `
  --path $windllpath `
  --path C:/Windows/System32/downlevel `
  --specpath ./dist/ `
  --distpath ./dist/dist `
  --workpath ./dist/build `
  --add-data "../html;html" `
  --add-binary "../.venv/Lib/site-packages/webview/lib;webview/lib" `
  src\main.py
Write-Host "> Complete"

您应该注意的是

  • 使用add-binary选项(与路径匹配)将PyWebView DLL包含在软件包中。
  • 将HTML文件与添加数据选项一起放置

成功创建exe后,尝试运行它。
image.png

我能够将其作为独立应用程序运行。

还有一个名为eel的库,可以实现具有类似HTML的GUI,但是它可以直接使用现有的Chrome(如果安装了扩展程序,也可以使用它们)。我无法采用它,因为它首先使用PyInstaller打包时,效果不佳。

PyWebView使用 EdgeHTML 不幸的是,它使用Trident(IE11)(尽管似乎有计划迁移到EdgeHTML)。由于PyWebView的JSAPI参数指定的Python对象的返回值是IE11不支持的Promise对象,因此将需要一种与常规HTML编码完全不同的方法。

但是,如果您不过度使用它,则该应用程序的GUI应该可以。它还具有诸如显示打开文件或文件夹对话框的方法。

2019/10/22后记:使用CEF Python

您现在可以在PyWebView中使用CEF。如果使用此功能,则可以使浏览器引擎成为Chromium(似乎它也支持MSHTML(Edge),但将来也将成为Chromium ...)。

要使用此功能,首先添加两个模块cefpython3pythonnet

1
2
pipenv install cefpython3
pipenv install pythonnet

当使用

PyInstaller创建EXE时,需要cefpython3目录中包含的DLL,因此请将以下命令添加到pyinstaller的调用代码中。

create_exe.ps1(已添加到pyinstaller选项中)

1
  --add-binary "../.venv/Lib/site-packages/cefpython3/;." `

最后,使用

,将参数gui="cef"添加到webview.start(),如PyWebView公式中所述。

main.py

1
2
3
# …
window = webview.create_window(title="Test Application", width=640, height=320)
webview.start(load_thread, window, gui="cef")

另外,如果将debug="true"添加到webview.start()方法的参数,甚至可以打开开发人员模式窗口。这使开发更加容易。

在CEFPython开发人员窗口

中跟踪JavaScript

使用CEFPython时,HTML以data-uri的形式加载到Chromium中。因此,在这种状态下很难从控制台遵循JavaScript。

在这种情况下,console.log在JavaScript的开头是合适的。

image.png

当您

时,行号将显示在右侧,从中您可以看到JavaScript来源。