Python中像Electron这样的Web转桌面开发框架,为什么不直接架设Web服务通过网络控制本地客户端实现程序功能?

如题,electron 桌面程序开发虽然类似 web 的开发,但是又和 web 开发不完全一样!

那为什么不直接在服务器上面建立 web 服务,通过网页来传输命令直接控制相应的客户端来进行操作,有没有这样的开发框架,请大家推荐。

比如简单的从服务器获取 doc 文件并在本地打开,建立 web 页面后,点击 web 打开按钮,服务器传输 doc 文件到本地客户端并执行 world 的打开命令。

这样的优势就是,web 界面完全是网页形式的,用各种 ie 浏览器都可以操作,而且可以使用 web 各种技术实现炫丽的界面。

有没有这样的框架请推荐一个?


Python中像Electron这样的Web转桌面开发框架,为什么不直接架设Web服务通过网络控制本地客户端实现程序功能?

38 回复

表示读了好几次都没读懂,建议组织语言再来一次。


这个问题问得挺有意思,本质上是在问“为什么要把Web技术打包成独立的桌面应用,而不是直接用浏览器访问一个本地服务”。

核心原因在于用户体验、系统集成度和分发部署的差异。Electron这类框架(如PyWebView, Eel, Flet)打包出来的就是一个标准的、独立的桌面应用(.exe, .dmg, .AppImage)。用户拿到手的感觉和用Chrome、Photoshop没区别——双击图标就打开,在系统任务栏里有自己的图标,可以离线运行,能直接调用本地文件系统、串口、USB设备等系统级API。它把整个浏览器引擎(Chromium)和你的Python后端都“内嵌”到了一个应用里。

而如果你选择架设一个本地Web服务(比如用Flask跑在127.0.0.1),然后让用户用浏览器去访问,会遇到几个实际问题:

  1. 启动流程割裂:用户需要先运行你的Python脚本启动服务,再手动打开浏览器输入localhost:5000。对普通用户极不友好。
  2. 像网站,不像软件:应用活在浏览器标签页里,共享浏览器的图标和菜单,容易被误关,缺乏“独立应用”的感知。
  3. 权限和弹窗:浏览器出于安全考虑,对访问本地文件、蓝牙等硬件有严格限制,通常会弹出确认对话框,体验不流畅。
  4. 依赖环境:你需要确保用户机器上有Python和正确的依赖包,而打包好的Electron应用就是一个独立文件,对环境零依赖。

简单说,Electron方案提供了原生应用般的封装体验,而本地Web服务更像一个需要手动搭建的开发环境。

所以,技术选型取决于你的目标:

  • 做需要深度系统集成、离线使用、独立分发的桌面软件 -> 选Electron或类似框架。
  • 做原型、内部工具,或者功能纯粹、不介意在浏览器中运行的本地工具 -> 本地Web服务更轻量、开发更快。

总结:要分发软件,就打包;做内部工具,本地服务更轻快。

本地搭个 web 服务器不就好了。。。

另外,web 迅雷可能是楼主这个想法的鼻祖

楼主你说的是 Chrome OS 吗?

可是断网了就没法用了,比如我们国内就用不了。

如果在浏览器执行, 怎么操作本地文件,调用系统 API 呢?
如果在独立应用内执行, 那也先得有应用啊。

我意思就是直接通过 web 来控制本地程序运行,主程序是 web 界面,每个客户端有后台服务程序,用于监听服务器发送的命令!

http://appstore.deepin.com/
CEF -> Chromium Embedded Framework

浏览器本来就是特殊的客户端。

electron 可以操作本地文件啊。如果我能操作你本地的文件,楼主你敢打开我给你的网址吗?

本地搭服务器有些应用是无法使用浏览器直接实现的,尤其是本地文件的操作及其他 exe 的远程执行,比如通过浏览器控制用一个串口程序打开 xml 文件显示波形图。

本地安装后台服务程序,监听服务器发来的命令!

不是 Chrome OS,这个属于一个操作系统,内部网络程序或者简单的互联网程序。

我只是有这么个想法,其实安装浏览器控件就就不需要安装本地后台服务程序了

首先楼主搞清了客户端和服务端开发了吗

你是说要我每打开一个目录,都得把打开目录的指令传到服务器,然后服务器原样传回来客户端再打开,然后客户端把文件列表传到服务器,服务器再把文件列表传回浏览器显示吗?
那我还不如把服务器跑在本地运行。

楼主说的这个,我之前在一篇介绍 英雄联盟的客户端架构的文章中见过。就是起两个进程,一个 HTML 进程做显示,另一个进程做逻辑和服务器通信。这两个进程通过 PRC ?交换数据。

浏览器要保证你的系统安全,很多权限不直接给你,要你通过扩展去实现。 打开个网页就把我本地的文件都拷了一遍,换你你放心用。

另外,不是 localhost 的网页和本地通信算是跨域吧? yaaw 这个 chrome 扩展就是走 json-rpc 控制本地运行的 aria2

可能楼主想要的是一个同样的客户端,把系统的这么多 API 全都实现掉。然后他使用不同的应用,都只需要跟这个通用客户端打交道即可。所以楼主其实是想要浏览器提供更多的系统级 API。那么问题来了,我如何确保我打开的网页不是恶意网站,不会把银行存款转走呢?

续上👆15 楼,为了保证网页安全,需要一种类似于 OAuth 的机制来授权?甚至需要像 360 一样对各个权限进行授权?因为不安全的网页调用系统 API,这安全性可以想象。



其实是我有这么个需求想找个框架简单实现:

属于心电软件的通用控制,由于我无法画出和设备显示一样的心电图形,而设备附带的单机软件可以,我通过服务器传送命令控制本地客户端将服务器的 xml 心电数据文件拷贝到本地,然后控制安装在本地的客户程序打开另外一个心电软件进行显示数据!

患者的登记及报告诊断已经通过 web 实现。

其实到这种程度,就和你安装银行控件或者安装 qq 一样了。首先我信任这个软件,而我软件的界面和控制端变成的浏览器,你给我网址我敢打开。

浏览器不就是这样的?

electorn 只是让你方便用 web 开发的方式开发本地应用程序,是类似 wpf、qt、javafx 这种层面的存在,和 lz 说的不搭边吧_(:з」∠)_

我好像懂楼主的意思了,楼主的意思是终端程序加个本地 web 界面

看了好多,可能我最近正在做的这个项目和楼主的需求一致,说下我的大致做法和遇到的坑
我这边主项目用 mfc 编写,进行系统钩子、文件操作、socket、sqlite 等操作,使用 mfc 的 web 控件来载入网页,我这里使用 vs2008 编译出来的项目,web 控件内核为 ie7 (这也是最坑的地方)。
mfc 的 web 控件相当强大,你可以使用 c++直接调用 js 的函数,也可以使用 js 调用 mfc 的函数,数据之间交互无障碍。
我这里为了载入快,所以使用的是本地 html/css/js 文件,效果不错,就是要专门为 ie7 做适配。

为了这个项目,我愣是学了前端的一些东西……哦,还有一点,我这里 js 用的是原生 js,并没有使用 jq,听说 jq 某版本后不再支持 ie9 以下的了?印象不深了,因为我这里对 js 要求不高,主要是传递数据,所以就直接用了原生 js

无法实现?麻烦请先搞懂什么是浏览器,什么是 Web 服务器,好好复习一下计算机原理。神烦这种啥都不懂上来就反驳别人的。

本质都是 web+nodejs,并没有什么差别。

这种情况用 Electron 也可以啊。WebSocket 连接服务器,服务器推送任务,客户端执行。

HTTP 头加个参数,或者 HTML 文件里加个参数可以开启新版本的 IE 内核。修改注册表也可以开启,但并不推荐这么做。Win10 中还有办法使用 Edge 内核。
上述方法的前提是系统中 IE 版本也要高。如果不想考虑这么多的话,可以直接用 CEF https://bitbucket.org/chromiumembedded 缺点是体积很大。

#25 cef 啊,这个之前研究了一下,不过因为我们客户端之前并没有推送 dll 的机制,所以只能暂时先这么解决,一步一步来吧,后期可能选择阉割的 chrome 内核

阉割的 chrome 内核?意思是你要自己修改编译一个内核?我觉得这么做成本太高,重复造轮子。
另外,你可以考虑把 cef 静态链接进 exe。

#27 自己做太麻烦了,网上有一些魔改的,貌似 10mb 大小吧,cef 静态链接啊,晚点看看大小吧

网上这类也只是业余研究的性质吧,不能保证稳定可靠的。我还是觉得 CEF 靠谱些。

#29 是啊,要不是因为不可靠,我也不会先用 ie7 对付了……

怎么感觉这是巨硬 dot net 框架最一开始的思路呢。。。

当你不再考虑 M$的框架后,就明白其他软件框架的思路是什么了?否则,还是继续 MFC、IE 吧,其他框架不适合你

计算机原理就不复习了!多谢回复,看你回复后,我又查询了下浏览器调用本地文件相关信息,受到很多启发,我说浏览器不支持本地文件操作确实不对。自己着手写了个简单的客户端,准备一会测试下。

我先在本地建立 web 服务,在浏览器访问 http://127.0.0.1/runexe?id=201708180002
通过截取路径来启动程序并传递参数

就是 web 版本的远程桌面。现在同类产品太多了。electron 这么大的软件,没什么市场价值。

我简单写了一个测试程序,直接控制本地 ecg 程序打开一个文件后检测关闭状态进行后期处理
’‘’
# -- coding: utf-8 --
from http.server import HTTPServer, BaseHTTPRequestHandler
import io, shutil
import re # 引入正则表达式对象
import urllib # 用于对 URL 进行编解码
import os, os.path, sys
import win32process, win32event
mainfile = os.getcwd()
class TestHTTPHandler(BaseHTTPRequestHandler):
# 处理 GET 请求
def do_GET(self):
# 页面输出模板字符串
templateStr =’’’
<html><head><title>QR Link Generator</title></head><body>%s<br><br><form action="/qr" name=f method=“GET”><input maxLength=1024 size=70
name=s value="" title=“Text to QR Encode”><input type=submit
value=“Show QR” name=qr></form><a href=’/runtest?DataRecive20160706185117’>http://127.0.0.1:8080/runtest?DataRecive20160706185117</a></body></html> ‘’’
# 将正则表达式编译成 Pattern 对象
pattern = re.compile(r’/qr?s=([^&amp;]+)&amp;qr=Show+QR’)
# 使用 Pattern 匹配文本,获得匹配结果,无法匹配时将返回 None
match = pattern.match(self.path)
qrImg = ‘’
teststr=match
teststr2=(self.path)
teststr3=teststr2.split(’\’)[0]
runname=teststr2[1:teststr2.find(’?’)]
xmlfilename=teststr2[teststr2.find(’?’)+1:]
if (runname==‘runtest’):
exe_path = ‘D:\pythontest\ecgfiles’ # sys.argv[1]
exe_file = ‘ECGView.exe’ # ‘.argv[2]
ECGPath=os.path.join(mainfile, “ecgfiles”, “ECGPath.dir”)
f = open(ECGPath, “w”) # 覆写模式
f.write(“D:\pythontest\ecgfiles\ecgdata\”+xmlfilename+".xml")
f.close()
try:
handle = win32process.CreateProcess(os.path.join(exe_path, exe_file),
‘’, None, None, 0,
win32process.CREATE_NO_WINDOW,
None,
exe_path,
win32process.STARTUPINFO())
running = True
except Exception as e:
print(“Create Error!”)
handle = None
running = False
while running:
rc = win32event.WaitForSingleObject(handle[0], 1000)
if rc == win32event.WAIT_OBJECT_0:
running = False
boday1=(templateStr % qrImg)
enc = “UTF-8”
encoded = ‘’.join(boday1).encode(enc)
f = io.BytesIO()
f.write(encoded)
f.seek(0)
self.send_response(200)
self.send_header(“Content-type”, “text/html; charset=%s” % enc)
self.send_header(“Content-Length”, str(len(encoded)))
self.end_headers()
shutil.copyfileobj(f, self.wfile)

httpd = HTTPServer((’’, 8080), TestHTTPHandler)
print(“Server started on 127.0.0.1,port 8080…”)
httpd.serve_forever()
‘’‘

ie ?兼容就蛋疼死了,不如内嵌一个浏览器,硬盘反正便宜。

推荐他山界面框架

回到顶部