Textual:用 Python 在终端与浏览器中构建现代用户界面的轻量级应用框架
【免费下载链接】textualThe lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.项目地址: https://gitcode.com/gh_mirrors/te/textual
Textual 是一个面向 Python 的快速应用开发(Rapid Application Development)框架,让你用一套简洁的 Python API 构建精致、可交互的用户界面,并能在终端或浏览器中运行同一套应用。本文以项目官方文档首页为核心,系统讲解 Textual 的定位、核心特性、安装方式、示例应用与生态,并结合仓库内真实源码深入剖析其开发范式,帮助读者快速上手并理解其底层机制。
什么是 Textual
Textual 由 Textualize.io 团队开发,是一个用于 Python 的快速应用开发框架。它的核心主张是:用简单的 Python API 构建复杂的用户界面,应用既可以在终端运行,也可以通过textual serve等工具在浏览器中运行。
仓库 pyproject.toml 中将其描述为 "Modern Text User Interface framework"(现代文本用户界面框架),当前版本为 8.2.8,采用 MIT 许可(文档首页特性卡片中也明确标注 "Textual is licensed under MIT")。该框架以 Python 3.9 及以上版本为目标(pyproject.toml中python = "^3.9"),支持 Linux、macOS、Windows,以及几乎所有 Python 能够运行的平台。
从文档首页的定位来看,Textual 面向的不仅是开发者——它把 Web 世界中成熟的组件化、响应式、CSS 样式等理念引入终端编程,同时保持 Python 开发者熟悉的编码习惯。
六大核心特性
文档首页以特性卡片的形式总结了 Textual 的核心能力,下面逐一展开并结合仓库验证:
| 特性 | 说明 |
|---|---|
| 快速开发(Rapid development) | 直接复用你已有的 Python 技能即可构建精美的用户界面,无需学习终端绘图细节 |
| 低要求(Low requirements) | 对硬件要求极低,甚至可以在树莓派这类单板计算机上运行 |
| 跨平台(Cross platform) | 支持 Linux、macOS、Windows,几乎在所有 Python 可运行的环境中都能工作 |
| 远程运行(Remote) | Textual 应用可以通过 SSH 远程运行,天然适合服务器场景 |
| CLI 集成(CLI Integration) | 应用可以直接从命令行提示符启动并运行,与现有工具链无缝衔接 |
| 开源(Open Source) | 基于 MIT 协议开源,可自由使用、修改与分发 |
其中"快速开发"与"跨平台"两大特性正是 Textual 框架设计的出发点:它把富文本渲染(底层基于 Rich)与异步事件循环、响应式状态管理整合在一起,让开发者把精力集中在业务逻辑上。
技术底座:异步 + 响应式 + 组件化
虽然入门时可以完全不接触异步编程(README 明确说明 "Textual won't force it on you"),但理解底层机制有助于写出更高质量的界面:
- 异步框架内核:Textual 本质是一个异步框架,这意味着你可以将应用与任何 async 库集成,处理网络请求、定时任务等并发场景。
- 响应式状态:通过 响应式属性(
reactive.var)声明应用状态,状态变化自动触发界面刷新。下面的计算器示例会详细演示watch_*与compute_*的用法。 - 组件化部件体系:Textual 提供了从按钮、树控件、数据表格、输入框到文本编辑器在内的丰富部件库,配合灵活的布局系统可以组合出任意需要的界面,且内置主题保证开箱即用的视觉效果。
环境要求与安装
根据 入门指南,Textual 要求Python 3.9 或更高版本(有条件请优先选择最新 Python)。平台方面,Linux 各发行版自带终端即可运行;macOS 默认终端仅支持 256 色,官方建议使用 iTerm2、Ghostty、Kitty 或 WezTerm 等现代终端;Windows 则推荐使用 Windows Terminal,运行效果最佳。如果你使用的是 Linux 控制台(非桌面环境),请参考 Linux 控制台说明。
从 PyPI 安装
pip install textual如果你计划开发 Textual 应用,还应同时安装开发者工具包:
pip install textual-dev若需要在 TextArea 部件中启用语法高亮,安装时请指定syntax附加依赖:
pip install "textual[syntax]"该 extras 在 pyproject.toml 中有完整定义,它通过 tree-sitter 系列包(要求 Python >= 3.10)为 Python、Markdown、JSON、TOML、YAML、HTML、CSS、JavaScript、Rust、Go、SQL、Java、Bash 等语言提供语法解析能力。
从 conda-forge 安装
Textual 也发布在 conda-forge 上,官方推荐使用 micromamba:
micromamba install -c conda-forge textual micromamba install -c conda-forge textual-devTextual CLI
安装开发者工具后,你将获得textual命令,其中包含一系列辅助构建应用的子命令。运行以下命令查看可用命令列表:
textual --help更多关于textual命令的用法参见开发工具指南。
快速体验:运行官方 Demo
安装完成后,一条命令即可感受 Textual 的能力:
python -m textual这条命令的入口在 src/textual/main.py:它实例化DemoApp并调用app.run()启动应用,退出后还会在终端打印一条致谢提示面板。Demo 应用本身位于 src/textual/demo/ 目录,包含多个展示部件与动画效果的子应用。
如果不安装也想体验,可以在装有 uv 的环境下运行:
uvx --python 3.12 textual-demo把应用搬到浏览器
Textual 应用在浏览器与终端中同样出色。任何 Textual 应用都可以用textual serve托管到 Web 端,方便分享:
textual serve "python -m textual"本地托管之外,还可以借助 Textual Web 的公网穿透能力,突破防火墙限制托管任意数量的应用。由于 Textual 系统要求低,你可以把它安装在任何 Python 可运行的地方,将任意设备变成"联网设备"——不需要桌面环境。
开发与调试工具
在终端里调试一个同样运行在终端里的应用是个经典难题,textual-dev包提供了解决方案:开发者控制台(dev console)可以从另一个终端连接到你的应用,除了系统消息和事件,你通过log输出的日志以及print语句都会出现在控制台里。此外,Textual 应用内置了模糊搜索命令面板(command palette),按ctrl+p即可打开,并且可以很容易地通过自定义命令进行扩展。
用 Textual 构建的生态应用
文档首页专门设置了 "Built with Textual" 板块,展示了一批基于 Textual 构建的真实应用,印证了框架在多种场景下的实战能力:
- Toad:面向 OpenHands、Claude Code、Gemini CLI 等 AI 编码工具的终端前端。
- Posting:生活在终端里的 API 客户端,用于开发与测试 API。
- Toolong:用于查看、tail、合并与搜索日志文件(含 JSONL)的终端应用,由 Textualize 团队自己开发。
- Memray:Bloomberg 开发的 Python 内存分析器。
- Dolphie:面向 MySQL/MariaDB 与 ProxySQL 的实时分析"单一玻璃面板"。
- Harlequin:易用、快速且美观的终端数据库客户端。
这些应用的官方屏幕截图保存在 docs/images/screenshots/ 目录中:
Posting 应用界面截图:终端内的 API 开发测试客户端
动手实践:官方示例应用拆解
文档首页的 Examples 板块以标签页形式内嵌了两个官方示例的完整源码(取自 examples 目录),这两个例子恰好覆盖了 Textual 开发的两个典型维度:极简启动与完整实战。
Pride 示例:最短可运行的 Textual 应用
examples/pride.py 是演示 Textual 入门概念的经典例子,完整代码如下:
from textual.app import App, ComposeResult from textual.widgets import Static class PrideApp(App): """Displays a pride flag.""" COLORS = ["red", "orange", "yellow", "green", "blue", "purple"] def compose(self) -> ComposeResult: for color in self.COLORS: stripe = Static() stripe.styles.height = "1fr" stripe.styles.background = color yield stripe if __name__ == "__main__": PrideApp().run()这个不足 20 行的应用集中体现了 Textual 的三个核心概念:
App子类:应用主体是一个继承自textual.app.App的类,if __name__ == "__main__"中调用run()启动事件循环。compose方法:以生成器方式声明界面结构,yield一个部件即挂载一个部件。这里通过循环生成 6 个彩条。- 程序化样式:
stripe.styles.height = "1fr"与stripe.styles.background = color演示了在代码中直接设置布局比例(1fr表示均分垂直空间)与背景色,这等价于 CSS 中的对应声明。
运行方式很简单:
cd examples python pride.pyCalculator 示例:响应式状态与 CSS 样式的完整实战
examples/calculator.py 是一个受 macOS 计算器启发、功能完整的"桌面级"计算器,支持鼠标点击按钮与键盘按键两种操作方式。它同时展示了 Textual 开发中最重要的三个进阶特性,值得逐行研读。
1. 响应式状态声明(var)
numbers = var("0") show_ac = var(True) left = var(Decimal("0")) right = var(Decimal("0")) value = var("") operator = var("plus")通过from textual.reactive import var声明的类属性即响应式状态。任何对它们的赋值都会自动触发对应watch_*方法(状态变化时调用)或compute_*方法(重新计算衍生值):
def watch_numbers(self, value: str) -> None: """Called when numbers is updated.""" self.query_one("#numbers", Digits).update(value) def compute_show_ac(self) -> bool: """Compute switch to show AC or C button""" return self.value in ("", "0") and self.numbers == "0" def watch_show_ac(self, show_ac: bool) -> None: """Called when show_ac changes.""" self.query_one("#c").display = not show_ac self.query_one("#ac").display = show_ac这里numbers一更新,Digits部件便自动刷新显示;show_ac则根据计算状态在 "AC"(清零)与 "C"(仅清除当前输入)两个按钮间自动切换。关于响应式机制的完整说明见响应式指南。
2. 事件分发与@on装饰器
按键事件通过on_key方法监听并映射到对应按钮 ID;按钮点击则用@on(Button.Pressed, ...)选择器式监听,支持按 ID 或 CSS 类精准路由:
@on(Button.Pressed, ".number") def number_pressed(self, event: Button.Pressed) -> None: """Pressed a number.""" assert event.button.id is not None number = event.button.id.partition("-")[-1] self.numbers = self.value = self.value.lstrip("0") + number @on(Button.Pressed, "#plus,#minus,#divide,#multiply") def pressed_op(self, event: Button.Pressed) -> None: """Pressed one of the arithmetic operations.""" self.right = Decimal(self.value or "0") self._do_math() assert event.button.id is not None self.operator = event.button.id".number"匹配所有带number类的按钮(数字键 0-9),"#plus,#minus,#divide,#multiply"匹配多个指定 ID 的运算符按钮。event.button.id.partition("-")[-1]从number-7这类 ID 中提取数字本身。整个计算逻辑用Decimal保证精度,异常时显示 "Error"。
3. CSS 文件与网格布局
应用通过CSS_PATH = "calculator.tcss"引入外部样式表 examples/calculator.tcss。该样式表用 Textual 的类 CSS 语法完成了计算器的全部排版:
#calculator { layout: grid; grid-size: 4; grid-gutter: 1 2; grid-columns: 1fr; grid-rows: 2fr 1fr 1fr 1fr 1fr 1fr; margin: 1 2; min-height: 25; min-width: 26; height: 100%; &:inline { margin: 0 2; } } Button { width: 100%; height: 100%; } #numbers { column-span: 4; padding: 0 1; height: 100%; background: $panel; color: $text; content-align: center middle; text-align: right; } #number-0 { column-span: 2; }要点解读:
layout: grid声明 4 列网格,grid-rows: 2fr 1fr ...让显示区占两倍高度,其余行等分;#numbers { column-span: 4; }让显示区横跨整行,background: $panel、color: $text引用的是 Textual 主题变量,自动适配当前主题;#number-0 { column-span: 2; }让 "0" 键横跨两列,模拟真实键盘布局;&:inline { margin: 0 2; }是父选择器(&)在inline模式下的样式覆盖——因为该应用在__main__中以CalculatorApp().run(inline=True)启动,inline模式专为嵌入式/内联运行场景调整边距。
计算器示例同时放在 docs/examples/ 对应的指南文档中使用,文档中所有部件截图的生成代码也都可以在 docs/examples 目录找到。
探索更多
- 从零开始:入门指南 提供了全部环境准备细节;教程 则循序渐进地构建一个完整应用。
- 深入主题:指南 目录覆盖 CSS、事件、布局、屏幕、测试、工作线程(workers)等全部主题;部件文档 逐个讲解内置部件的用法。
- 学习范例:仓库 examples/ 中还有计算器、时钟、代码浏览器、JSON 树、字典应用等更多可直接运行的例子(例如
python code_browser.py ../)。 - 测试与维护:Textual 内置了先进的测试框架,配合解耦的组件设计,确保应用可以长期维护。
- 遇到问题:参阅帮助页面 获取社区帮助或报告 Bug。
【免费下载链接】textualThe lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.项目地址: https://gitcode.com/gh_mirrors/te/textual
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考