Python中的curses编程2025 年 3 月 7 日 | 阅读 15 分钟 Curves 库提供了独立于终端的方式来控制 VT100 和 Linux 控制台等字符终端上的屏幕绘制和键盘,以及模拟终端和程序。许多操作都是通过不同的控制代码执行的,其中光标移动、屏幕滚动和擦除区域都使用不同的代码,这些代码对于不同制造商和型号的终端可能具有不同的功能。 现在,大多数接口都是图形界面,因此使用这种技术可能显得过时。但是,在某些情况下,它仍然是必需的。例如,有些系统资源可用性低,有些 Unix 设备无法运行 X 窗口系统应用程序。这对于操作系统安装程序或内核配置实用程序等项目也适用,它们需要在图形环境甚至不存在之前“工作”。 curses 库提供了在屏幕上操作文本窗口的基本功能。它使程序员能够打开多个非并发窗口,在它们上写入并重新着色或重塑它们。该库隐藏了系统必须向终端发送正确控制代码以获取给定输出的事实细节。但 curses 不提供额外的用户界面组件,如按钮、复选框或对话框。对于这些类型的功能,您可能需要更广泛的用户界面捆绑包,例如 Urwid。 Curse 是一个最初与 BSD Unix 系统一起使用的库。随后,对原始库的更多增强以及附加功能被集成到 AT&T 随后的 System V Unix 版本中。自从原始 BSD curses 以来,AT&T 接口已被 ncurses(一个开源实现)取代。在开源 Unix 系统(例如 Linux 或 FreeBSD)上运行的免费实现,例如,可能使用 ncurses 作为 curses。 当今大多数商用 Unix 系统都是使用 System V 代码开发的,因此它们应该能够支持 ncurses 提供的功能。尽管如此,一些在大多数实际专有 UNIX 中使用的旧版本 curses 可能不包含此处描述的所有选项。 如果您使用的是 Windows 平台,请注意安装是在 Python.org 中完成的,并且不包含 curses 模块。但是,有一个移植版的 UniCurses,它类似于系统 BestCurses,并且在 Windows 平台上运行。 Python Curses 模块Python 的 curses 模块实际上提供了一个非常简单的接口来调用 curses 库的低级 C 函数。因此,对于有 C 语言编程背景的人来说,移植到 Python 应该非常容易。Python 接口的一个显著简化是,一些 C 函数,包括 addstr()、mvaddstr() 和 mvwaddstr(),都包含在一个 addstr() 方法中,使代码易于管理和理解。他们建议通过简化实现这一点,本指南稍后将详细解释。 本 HOWTO 将尝试让您熟悉使用 Python 编写带 curses 的文本用户界面。它不是所有可用 curses API 的列表,也不是关于如何使用它的全面指南。要获得更完整的指南,您必须查阅 Python 库手册,特别是关于 ncurses 和 ncurses 的 C 手册页。但是,本指南将帮助用户对在 Python 中使用 curses 获得基本理解和实际方法。 启动和结束 Curses 应用程序在使用 curses 之前,您必须导入库;尽管如此,还有一个额外的步骤是初始化 curses 库。这是通过调用 initscr() 函数来完成的。此函数执行几个重要的任务:顾名思义,它确定您正在使用的终端,向终端发送任何相关的初始化代码以确保其配置正确,并设置 curses 在系统内工作所需的所有内部数据。 如果此初始化成功,initscr() 将返回一个覆盖整个屏幕的“Normal”类型窗口。此对象通常称为 stdscr,这是 curses 在 C 中实现时使用的相应变量的名称。此 stdscr 窗口对象用作在 curses 应用程序中打印文本和控制打印屏幕的默认访问点。 安装Curses 是一个 Python 包库,用于开发文本界面。在基于 Linux 或 MacOS 的系统中,curses 有必要的依赖项,它们通常包含在包中。但是,Windows 用户使用的是一个名为 curses 的包,但这不是默认安装的一部分。此功能需要一个名为 Windows-curses 的 Windows 包,需要从 PyPI 下载才能在 Windows 上安装。这个特殊的包在 Windows 上继续 curses 模块,允许开发人员在 Python 中构建终端界面。您可以使用以下命令安装 您可以验证 curses 是否已安装。为此,打开命令提示符,键入 Python 打开 Python。然后,导入 curses。如果没有错误,则 curses 已成功安装。 Curses 的核心概念现在,最好转向使用“curses 库”这一更具进步性的话题,但首先熟悉基础知识会很有用。这些基础知识将有助于为如何不仅理解图书管理员如何组织当今系统,而且了解进步发展奠定初步基础。需要熟悉的关键概念包括
这些基本概念将首先进行探讨,在进行更高级的任务之前提供坚实的基础,例如:首先,将描述这些基本概念,以启发没有机会处理此类任务的读者,例如
在 Curses 中创建屏幕现在,curses 库已成功导入并准备好启动。使用 Curses 库,您将获得一个“主窗口”,它会擦除终端并为您的应用程序提供一个区域。此主窗口将专门用于显示屏幕上在某个时间点显示的所有文本和图像。 在下面的示例中,我们将演示如何启动 curses 环境以及如何获取我们将与之交互的主窗口;我们将它称为“屏幕”。从这个中心点,将执行所有活动,例如写入文本、管理输入和操作终端屏幕。 当 curses 库启动时,它将完全控制终端屏幕。它清除所有内容并具有格式良好的布局,这将使我能够打开更多窗口和子窗口,以及其他功能,例如高级终端颜色和按键事件等等。在此阶段,终端将停止作为典型终端运行,这意味着通过标准输入/输出框架执行的任何操作都将通过 curses 完成。 以下步骤概述了初始化 curses 并获取应用程序主屏幕窗口的过程
让我们创建一个屏幕 既然已经确认导入“curses”模块成功,下一步就是运行该模块。在初始时刻,“curses”会建立一个新窗口并清除终端,以实现新窗口的可视化。在以下示例中,将展示如何正确初始化“curses”模块以获取窗口实例——它将作为后续操作的基础。因此,在我们讨论的所有示例中,我们将此主窗口称为“屏幕”,因为它让您有机会根据此处看到的特定目的来工作和管理屏幕。 代码 输出 Preparing to initialize screen... Screen initialized. Window ended. 说明 创建接口)由“main(stdscr)”函数控制。首先,屏幕被清空,并调用在位置 0, 0 处显示字符串“Hello, World!”的命令。curses.wrapper(main) 成功设置和关闭 curses 环境,以确保终端在运行后和出现异常时返回其默认状态。在 f() 中,屏幕重新发送以执行更改,程序使用 curses.napms(2000) 暂停 2 秒。在此之后,屏幕再次刷新,并在程序结束时,在 curses 接口之外打印消息“Window ended.”。如果出现任何错误,它将被捕获并通过 sys.stderr 打印。 现在我们已经介绍了如何初始化一个空白屏幕以及如何在程序完成后清理它,让我们继续程序的第三部分,并在屏幕上添加一些文本。在这里,我们像以前初始化屏幕一样输入,但将其添加到此字符串显示在屏幕上。值得一提的一件重要事情是,每当内容更新时,您都必须使用 refresh() 函数,以便每个人都可以看到这些更改。这有助于确保您开发的新内容或您所做的更新在终端中呈现。通过这种方式,它可以定义强大而丰富的基于文本的接口,可以与用户动态交互。 代码 说明 有了这种理解,人们可以将文本放置在屏幕上的任何位置,从而创建多种形式的文本输入/输出。这些知识使您能够完成许多事情,尽管您可能想了解该包的一些限制,例如最大行数和列数。如果您希望填充整个屏幕或绘制边框,这些是您需要知道的尺寸。我们将在本中心的后续部分中找到查找此类限制的方法。 在 Curses 中清除屏幕通过在每个单元格中键入带有空格字符的黑色填充单元格来擦除终端屏幕会很累。但是,有一种更好、更简单的方法可以实现这一点。Windows 函数的 curses 包有一个 clear() 函数,它可以用一个命令擦除终端上的所有内容,留下一个空白且可供使用的终端。这项工作确保终端刷新并准备好进行新的输出,而无需系统进行人工干预。 代码 输出 Greetings, this message will vanish in 3 seconds 说明 上述代码使用 curses 创建一个具有基于文本的用户界面的应用程序。它使用 curses.initscr() 创建一个由 curses 用于写入和绘制的窗口,该函数初始化屏幕以供进一步操作。然后,代码通过 addstr() 函数写入消息“Greetings, this message will vanish in 3 seconds.”。之后,它使用“refresh”函数刷新窗口,然后使用参数“3000”的“naps”函数等待 3 秒。之后,它使用 clear() 清除屏幕,再次刷新屏幕,之后,它使用 pause() 等待 3 秒,然后使用 curses.endwin() 结束 curses 会话。这有效地显示了一条消息,该消息等待一段时间,然后清除整个屏幕,然后退出。 Curses 中的窗口Curses 提供了两个基本概念:值是窗口和垫。到目前为止,我们主要使用一个窗口,即主窗口。但是,curses 允许您创建任意数量的窗口,不同大小,并将它们放置在屏幕上的任何位置。可以在主屏幕窗口中使用的所有功能,例如使用 add() 等方法显示文本或使用 add() 显示字符,都可以由这些窗口执行。 此外,窗口本身也提供复杂程度不同的功能。可以将窗口的内容写入文件或从文件读取内容到窗口中。还可以设置边框和背景字符,甚至可以在窗口中打开一些较小的窗口。灵活性非常有效,因为它提供了 DITA 方式来处理基于文本的用户界面。 在这里,我们还将演示一种通用技术,通过这种技术可以创建一个新窗口,在其中放置一些文本,最后,可以在屏幕上移动窗口。它还演示了当文本到达窗口宽度时,窗口内的文本将自动放置在新行上,从而避免了内容隐藏的问题。通过此功能,人们可以在有限的空间中有序地呈现大量或复杂的文本,从而轻松管理 UI。此外,我们还可以看到移动窗口的简便性,因为我们将当前窗口移动到新位置,这显示了 Curses 处理多个移动窗口的能力。 代码 输出 Message from 2,3 A longer message from 3,10 说明 此代码设置 curses 接口的启动,以在终端接口中创建窗口。首先,创建主窗口,然后在位置 (1, 1) 创建子窗口,其长度和宽度分别为 10 和 25。在此步骤中,文本被添加到子窗口中并显示 2.5 秒。然后屏幕被清除,子窗口的新位置是 (5, 5),并且子窗口被刷新。最后但并非最不重要的一点是,子窗口被清除并再次擦除,并且如果程序结束,释放“curses”会话将使终端恢复其默认状态。 Curses 中的垫窗口垫是可滚动的表单,其中包含的内容可能比垫的布局部分多。与其他窗口相比,垫使在可滚动或可导航视图中处理更大内容成为可能。 代码 说明 这是一个简单的 Python 脚本,它借助 curses 库实现了一个小型应用程序。它使用 curses.initscr() 启动一个新屏幕:它创建一个新垫,这是一个尺寸为 100 * 100 的可滚动窗口,并向其中添加一个字符串文本。pad.refresh() 方法将垫的一部分放到屏幕上,它从坐标 (5, 5) 开始,它显示的区域是 15 x 20。在 3 秒(暂停 3000 毫秒)后,程序退出 curses 操作模式 - curses.endwin()。 Shell Out值得一提的是,当您调用 curses 时。大多数情况下,它的 endwin() 也会将您的终端重置为原始设置。但是如果您调用屏幕,建议在调用 refresh() 方法之后,您可以恢复您的自定义屏幕。在这种情况下,您将不得不吟诵一些咒语。最后,我们再次使用 endwin() 函数返回正常的终端,即 STDOUT。如果您希望隐藏自定义屏幕以直接在下面的终端上执行命令/脚本或切换回交互式界面,此功能非常有用。 “shelling out”的概念可帮助您轻松自由地在自定义基于 curses 的应用程序屏幕和标准命令提示符之间切换。通过这种方式,您可以执行维护应用程序上下文的任何终端命令。虽然 shell 附件允许您轻松切换回应用程序,但它是一种处理任务的灵活方式,而不会冻结界面状态。 代码 输出 Hello! You will now be taken to a command prompt... Program initialized... I'll be here when you return. Opening command prompt... 说明 此 Python 代码使用 curses 函数设计一个基于终端的 UI,该 UI 提示用户输入一些内容,然后打开命令行。首先,它使用 curses 创建屏幕。然后,它使用 initscr() 并使用 screen.addstr() 显示消息“Hello! You will now be taken to a command prompt...”。在下一步中,借助 curses.napms(2000),会有一个 2 秒的短暂停,然后使用 curses 关闭屏幕。通过 endwin() 释放终端的控制权。然后它通过使用 subprocess program.call() 执行命令提示符,为 Windows 用户选择 cmd.exe,为其他操作系统选择 sh。如果用户退出 shell,则会设置几秒钟的暂停,然后屏幕重新绘制并清除。基于 curses 的屏幕控制的垂直组合共享 shell 进程的执行。 查找屏幕尺寸在 Python 中开发使用 curses 库的应用程序时,将应用程序的行为保持在当前可用终端尺寸的范围内非常重要。不遵循准则导致的主要问题包括显示问题,例如文本被截断或根据用户的屏幕尺寸渲染不佳。虽然可以使您的应用程序动态或设计为与各种终端尺寸相对应,但建议您至少查看终端尺寸以确定其是否足够。大多数终端使用的一些安全通用尺寸是 80 列 x 24 行。为此,您可以使用 curses 获取用户终端的精确尺寸,以便应用程序在提供的参数内良好运行。 代码 输出 Rows: 6 Columns: 182 说明 此 Python 代码通过 curses 模块中的此函数启动终端。初始窗口使用 initscr() 创建,终端屏幕的尺寸通过使用 screen.getmaxyx() 获取。然后,它在使用 curses.endwin() 获取尺寸后擦除 curses 会话。最后,它使用格式化字符串在控制台上显示总行数和列数。 结论简而言之,使用 curses 在 Python 中编程是一个强大而灵活的库,用于在终端应用程序中创建基于文本的用户界面 (TUI)。该工具只需几行代码即可实现键盘输入处理、屏幕操作以及文本定位、着色和窗口管理。借助 curses,程序员可以构建交互式和动态界面,而无需任何图形工具;因此,它是生成不需要或冗余 GUI 的系统的替代方案。 |
我们请求您订阅我们的新闻通讯以获取最新更新。