python curses addstr 错误 - 但仅在我的电脑上

2 投票
3 回答
2489 浏览
提问于 2025-04-16 14:05

我在写一个小程序,这个程序会从一个列表生成一个菜单,使用的是curses库(就是Python自带的那个库)。在这个过程中,我遇到了一个奇怪的问题(如果你想看,我下面有这个程序的详细注释版)。简单来说,当我用os.listdir生成的列表时,curses会崩溃,显示addstr错误,但如果我用一个固定的列表,就没问题。这听起来完全没有道理,对吧?列表就是列表,不管叫什么名字,列表应该都是一样的,对吧?

事情变得更复杂了。我把代码发给了一个主要用python2.6的朋友(而我最开始是用python3.1写的)。他取消了broken_input()的注释(这个函数用来获取os.listdir生成的信息),他说对他来说一切正常。我同时安装了python 2.6和3.1,所以我把程序的开头改成让它在2.6下运行,结果(在取消注释broken_input()后)对我来说,还是出现了addstr错误(但用固定输入运行就没问题……不过这除了证明概念外,完全没用)。

所以,我的问题是:我的Python安装有什么问题吗?(我在用Ubuntu lucid,安装了python2.6.5和3.1),如果有,我该怎么修复它,让curses能正常执行这个代码。如果不是我的Python安装,那我该怎么用curses实现同样的功能(也就是:从一个包含任意数量项目的列表中绘制一个菜单,并给这些项目编号,让用户可以根据编号选择)。

#!/usr/bin/env python3.1
"""curses_mp3eater.py: a curses-based implementation of my mp3eater program;
diplays the contents of cwd, allows user to make a selection. But I'm having
problems getting it to iterate over a list.
v0.1 03.14.11
by skookie sprite
address@gmail.com
"""

import curses, curses.wrapper, os, sys


def working_input():
    """the following is demo code to demonstrate my problem... main will accept the following,
    but won't accept the product of a directorylist for reasons that I can't figure out."""
    dircontents=['this','is','a','list','','and','it','will','iterate','fine','in','the','(main) function.']
    return dircontents

def broken_input():
    """this is the code that I NEED to have work... but for reasons beyond me will not iterate in
    the main function. It's a simple list of the contents of the CWD."""
    cwd=os.getcwd()
    dircontents=[]
    for item in os.listdir(cwd):
        dircontents += [item]
    return dircontents

def main(stdscr):
    """This is the program. Designed to take a list of stuff and display it. If I can solve
    that hurdle, I'll add selection mechanisms, and break it across screens - amongst other
    things. But, currently, it can only accept the demo code. Uncomment one or the other to
    see what I mean."""
    #broken_input returns an addstr() ERR, but I don't see the difference between working_input
    #and broken_input as they are both just lists. 
    #working_input() is demo code that illustrates my problem
    stuffin=working_input()
    #stuffin=broken_input()

    #the rest of this stuff works. The problem is with the input. Why?
    linenumber=int()
    linenumber=6
    itemnumber=int()
    itemnumber=1

    stdscr.clear()
    stdscr.border(0)

    for item in stuffin:
        stdscr.addstr(linenumber, 10, '%s   -   %s' % (itemnumber, item), curses.A_NORMAL)
        linenumber += 1
        itemnumber += 1

    curses.doupdate()
    stdscr.getch()



if __name__ == '__main__':
    curses.wrapper(main)

3 个回答

0

这个问题在addch的手册页面中有解释:

addchwaddchmvaddchmvwaddch这些函数的作用是把一个字符放到指定的窗口的当前位置,然后光标会自动移动到下一个位置。它们的功能类似于标准输入输出库中的putchar(3)。如果光标移动到了右边的边缘,会发生以下情况:

  • 光标会自动跳到下一行的开头。

  • 如果当前的滚动区域到达底部,并且scrollok被启用,滚动区域会向上滚动一行。

  • 如果scrollok没有被启用,那么在右下角写字符是可以成功的,但会返回一个错误,因为无法换到新的一行。

给定的程序没有处理来自右下角(可能应该说“角落”)的错误,也没有调用scrollok来允许数据向上滚动。在后者的情况下,你会丢失被滚动上去的信息,而处理这个异常可以让你在显示一屏数据后进行提示,然后选择退出或者显示更多数据。

0

在使用addstr添加文本之后,记得用screen.scrollok(1)来允许文本滚动。

5

你在屏幕上放了太多东西,所以给addstr传递了一个超出范围的行号。如果你创建一个空的目录来运行这个程序(或者把你的终端窗口调大),它就能正常工作了。

要解决这个问题,在main函数的输出循环之前,先检查一下窗口里的行数。

撰写回答