编程开发与计算机科学

Pynecone 拔草 附应用的手动部署方法

Pynecone 是一个纯 python 的 Web App 开发框架。它的后端基于 Python 的 FastAPI 框架,前端基于 Node.js 的 Next.js 框架。但使用它不需要书写任何前端代码,可以完全用 Python 一把梭。听上去非常诱人,但实际如何呢?

一个简单 Pynecone 应用的代码如下:

pythonimport pynecone as pc


class State(pc.State):
    text: str = 'Hello, World!'
    
    def goodbye(self):
        self.text = 'Goodbye, World!'

def index():
    return pc.text(State.text, on_click=State.goodbye)

app = pc.App(state=State)
app.add_page(index, route='/')
app.compile()

Pynecone 会为每个 Session 维护一个 State 上下文,这个状态数据是保存在服务器端的,只能通过修改 State 的 Props 来间接改变视图。其原理是, Pynecone 生成的前端代码会通过一个 WebSocket 连接和后端进行交互。当用户进行了某个前端操作后,前端会将该事件通过 WebSocket 连接发送给后端,后端将改变后的 State 返回给前端,最后前端更新视图。由于所有前端操作都需要和后端交互,在网络不佳的情况下,会导致前端操作响应很慢

……

发送 Ctrl+C 事件终止 Windows 控制台进程

偶然在 Nuitka 的代码中发现一个未被触发的 BUG 。问题代码位于 OnefileBootstrap.c 的 cleanupChildProcess() 函数中。这段代码中第 654 行的 GenerateConsoleCtrlEvent() 总是返回 FALSE ,导致子进程无法收到 CTRL-C 信号。不过由于 Nuitka 的代码中只有 cleanupChildProcess(false) 调用,因此这个 BUG 正常情况下不会被触发。不幸的是,本人 fork 了 Nuitka 的项目 Nuitka-winsvc 正好触发了这个 BUG 。Nuitka-winsvc 为 Nuitka 增加了编译为 Windows 服务的选项。当停止服务时,需要向子进程发送 CTRL-C 信号来优雅结束子进程

使用 Nuitka 将 Python 程序编译为 Windows 服务

原来 Nuitka 商业版通过插件已经实现了编译 Windows service 的功能,但开源版本不提供此功能。掏钱是不可能掏钱的。本人 fork 了 Nuitka 项目,加入了编译 Windows service 的功能,只要在编译时加入 --windows-service 参数就将 Python 程序能构建成 Windows service 了:

shellpip install nuitka-winsvc
nuitka --onefile --windows-service --windows-service-name=myservice main.py

项目地址: https://github.com/tabris17/Nuitka-winsvc

在前文《Nuitka 编译时注入自定义 C 代码》中介绍了在 Nuitka 编译时注入自定义代码的方法。本文将介绍如何通过这种方法将 Python 程序编译成 Windows 服务。

……

Nuitka 编译时注入自定义 C 代码

Nuitka 是一款用 Python 实现的 Python 编译器,可以生成独立的可执行文件。其原理是生成 C 代码,然后使用 Scons 调用 C 编译器进行编译构建。据说使用 Nuitka 编译后的程序性能比 CPython 更好,和传统的打包工具 py2exe 与 PyInstaller 相比, Nuitka 的优势相当明显。

Nuitka 的使用也十分简单。比如要将下面的 main.py 文件进行打包:

python# main.py

print("Nuitka")

首先安装 Nuitka 和建议安装的三方库:

shellpip install nuitka ordered-set zstandard

另外,编译 C 代码还需要一个支持 C11 标准的 C 编译器。 Windows 系统上可以安装 Visual Studio 2022 或者 MinGW64 。然后就能用 nuitka 命令进行编译了:

……

Python 3.5 之后的新特性

Python 自 3.5 版本起,至当前 3.11 版本为止,变化相当大,引入了众多的新特性,了解这些变化对编写兼容性代码尤为重要。本文整理的一些版本的重要变化。

……

快速了解 SOCKS5 代理协议

SOCKS5 是最常见的代理服务协议,服务通常使用 1080 端口,支持代理 TCP/UDP 网络协议。协议由 RFC 1928 定义,也可以阅读非官方翻译的中文版。本文主要用于快速入门,省略了协议中不常用的部分。文中提供了协议的部分 Python 代码实现。

……

asyncio.DatagramProtocol 收到错误后停止响应

Python 官方文档提供了一个使用 asyncio 创建 UDP Echo Server 的示例,代码如下:

……

Python asyncio 模块实现简单异步 https 请求

网上关于 asyncio 实现异步 https 请求的代码几乎都是基于Python 第三方库 aiohttp 的,而我仅需要一个无第三方依赖的、能一键运行的简单 Python 脚本。翻了翻官方文档,也没有什么值得参考的 sample 代码。无奈只能自己动手撸一个。

以下示例代码的作用是,请求百度首页,并将响应打印出来。支持 Python 3.7 及以上的版本。

……

Python 信号处理在不同平台上的差异

在前文《为何 Windows 下无法用 Ctrl+C 终止 Python 进程》中,虽然解释了产生该现象的原因,但却没有解释为何同样的代码在 Linux 下就可以用 Ctrl+C 来中止。究其原因,是由于在操作系统层面,Linux 和 Windows 对 SIGINT 的信号处理方式不同所导致的。

……

Python 的 signal 处理与 print() 的 reentrant call 运行时错误

在前文《为何 Windows 下无法用 Ctrl+C 终止 Python 进程》中,讲解了 Python 信号处理的基本原理。当时为了撰写文章而编写了一些测试代码,在运行某例测试代码时,发生了奇怪的 reentrant call 运行时错误。代码如下:

……