ZetCode

Python os.get_terminal_size 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨了 Python 的 os.get_terminal_size 函数,该函数用于检索终端尺寸。我们将介绍使用模式、回退值和实际的终端格式化示例。

基本定义

os.get_terminal_size 函数返回终端尺寸,包括列数(宽度)和行数(高度)。它在 Python 3.3+ 版本中可用。

返回一个名为 os.terminal_size 的命名元组,包含 columns 和 lines 属性。如果无法确定终端大小,则返回回退值或默认值 (80, 24)。

基本终端尺寸检查

最简单的用法是检索当前终端尺寸。此示例展示了通过属性和索引访问尺寸值的方式。

basic_size.py
import os

# Get terminal size
size = os.get_terminal_size()

# Access via attributes
print(f"Terminal width: {size.columns} columns")
print(f"Terminal height: {size.lines} lines")

# Access via index
print(f"Dimensions: {size[0]}x{size[1]}")

这演示了访问尺寸的两种方式。命名元组提供了清晰的属性名称(columns,lines),并保持了索引兼容性。

输出将根据您运行时的实际终端窗口大小而有所不同。

提供回退值

当无法确定终端尺寸时(例如在非终端环境中),您可以指定回退尺寸。这可以防止使用默认值 (80, 24)。

fallback_size.py
import os

# Custom fallback dimensions
fallback_size = os.terminal_size((120, 30))

# Get size with fallback
size = os.get_terminal_size(fallback_size)

print(f"Using dimensions: {size.columns}x{size.lines}")

# Alternative tuple fallback
size = os.get_terminal_size((100, 20))
print(f"Alternative fallback: {size.columns}x{size.lines}")

第一种方法使用 os.terminal_size 作为回退值。第二种方法使用简单的元组,它会自动转换。

当在 IDE 中运行或重定向输出时,终端大小检测失败,回退值非常有用。

动态文本换行

使用终端宽度,我们可以实现动态文本换行,以适应当前的终端大小。这可以创建更好格式化的输出。

text_wrapping.py
import os
import textwrap

def print_wrapped(text):
    width = os.get_terminal_size().columns - 4  # Account for margins
    wrapper = textwrap.TextWrapper(width=width)
    print("\n".join(wrapper.wrap(text)))

long_text = ("This is a long paragraph that needs to be wrapped "
            "according to the current terminal width. The text will "
            "automatically adjust to fit within the available space.")

print_wrapped(long_text)

这通过从终端宽度中减去边距来计算可用宽度。然后,textwrap 模块处理单词边界处的换行。

调整终端大小并重新运行将产生不同的换行行为。

进度条宽度调整

终端宽度对于进度条至关重要。此示例展示了一个动态进度条,该进度条填充可用宽度。

progress_bar.py
import os
import time

def show_progress(iteration, total):
    width = os.get_terminal_size().columns - 10
    progress = int(width * iteration / total)
    bar = "[" + "#" * progress + " " * (width - progress) + "]"
    print(f"\r{bar} {iteration}/{total}", end="", flush=True)

# Simulate progress
for i in range(1, 101):
    show_progress(i, 100)
    time.sleep(0.05)
print()  # Newline after completion

进度条使用几乎完整的终端宽度,为计数器保留空间。它使用回车符就地更新。

当在执行期间调整终端大小时,条形图宽度会自动调整。

表格列大小调整

终端宽度有助于创建大小合适的表格。此示例根据内容和可用宽度按比例分配列。

table_columns.py
import os

data = [
    ["ID", "Name", "Description", "Value"],
    [1, "Item A", "First sample item", 42.5],
    [2, "Item B", "Second item with longer description", 127.3],
    [3, "Item C", "Short", 8.99]
]

def print_table(rows):
    term_width = os.get_terminal_size().columns
    col_widths = [
        max(len(str(row[i])) for row in rows)
        for i in range(len(rows[0]))
    ]
    
    # Adjust for terminal width
    total_needed = sum(col_widths) + 3 * (len(col_widths) - 1)
    if total_needed > term_width:
        scale = term_width / total_needed
        col_widths = [int(w * scale) for w in col_widths]
    
    # Print rows
    for row in rows:
        print("  ".join(str(cell).ljust(width) 
              for cell, width in zip(row, col_widths))

print_table(data)

这基于内容计算初始列宽,然后在需要时缩小以适应终端宽度。每个单元格在其列中都是左对齐的。

表格在适应不同终端尺寸的同时保持可读性。

垂直空间管理

终端高度有助于管理垂直输出。此示例根据可用行数对长内容进行分页。

pagination.py
import os

def paginate_content(lines):
    height = os.get_terminal_size().lines - 3  # Reserve space for prompts
    current = 0
    
    while current < len(lines):
        print("\n".join(lines[current:current+height]))
        current += height
        if current < len(lines):
            input("-- Press Enter for more --")

# Generate sample content
content = [f"Line {i}: Sample content..." for i in range(1, 101)]
paginate_content(content)

这一次显示一页内容,并在屏幕填满时暂停。高度保留考虑了命令提示符和分页控件。

用户可以舒适地查看长输出,而无需滚动浏览内容。

响应式 UI 布局

对于终端应用程序,响应式布局可适应终端尺寸。此示例显示了一个多面板布局,该布局可适应大小更改。

responsive_ui.py
import os

def draw_layout():
    size = os.get_terminal_size()
    width, height = size.columns, size.lines
    
    # Header
    print("=" * width)
    print("RESPONSIVE TERMINAL UI".center(width))
    print("=" * width)
    
    # Calculate panel sizes
    left_width = width // 3
    right_width = width - left_width - 1  # Account for separator
    
    # Content rows (reserve 4 lines for header/footer)
    for i in range(2, height - 2):
        if i == 3:
            left = "MAIN MENU".ljust(left_width)
            right = f"Terminal: {width}x{height}".ljust(right_width)
        elif i == height // 2:
            left = "SELECTION".ljust(left_width)
            right = "CONTENT AREA".center(right_width)
        else:
            left = "".ljust(left_width)
            right = "".ljust(right_width)
        
        print(left + "|" + right)
    
    # Footer
    print("=" * width)
    print(f"q: quit | r: refresh".ljust(width))

while True:
    draw_layout()
    cmd = input("Command: ")
    if cmd.lower() == 'q':
        break

这创建一个双面板布局,该布局在每次绘制时重新计算尺寸。页眉、页脚和内容区域会调整为当前的终端大小。

按下“r”会重绘布局,在调整终端大小后显示更改。

常见用例

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 Python 教程