python curses使用


python 中curses封裝了c語言的curses,把c中復雜部分簡單化,比如addstr(),mvaddstr(),mvwaddstr()合並成了一個addstr()方法。

一、語法入門

1、打開和關閉一個curses 應用程序

在任何代碼執行前都先要初始化curses。初始化操作就是調用initscr()函數,如下。該函數根據不同設備返回一個window對象代表整個屏幕,這個window對象通常叫做stdscr,和c語言報錯一致。

import curses
stdscr = curses.initscr()

使用curses通常要關閉屏幕回顯,目的是讀取字符僅在適當的環境下輸出。這就需要調用noecho()方法

curses.noecho()

應用程序一般是立即響應的,即不需要按回車就立即回應的,這種模式叫cbreak模式,相反的常用的模式是緩沖輸入模式。開啟立即cbreak模式代碼如下。

curses.cbreak()

終端經常返回特殊鍵作為一個多字節的轉義序列,比如光標鍵,或者導航鍵比如Page UP和Home鍵 。curses可以針對這些序列做一次處理,比如curses.KEY_LEFT返回一個特殊的值。要完成這些工作,必須開啟鍵盤模式。

stdscr.keypad(1)

關閉curses非常簡單,如下:

curses.nocbreak()#關閉字符終端功能(只有回車時才發生終端)
stdscr.keypad(0)
curses.echo() #打開輸入回顯功能

調用endwin()恢復默認設置

curses.endwin()

調試curses時常見的問題就是curses應用程序結束后沒有重置終端到之前的狀態,把終端弄的一團糟。python中該問題經常是因為代碼有bug,發送異常引起的。比如鍵盤敲入字符后屏幕不回顯,這讓shell用起來非常困難。

為了避免這樣的問題,可以導入curses.wrapper模塊。這個函數做了一些初始化的工作,包括上面提到的和顏色的初始化。然后再執行你提供的函數,最后重置。而且被調用的函數寫在try-catch中。

2、打開新窗口和pad

 通常調用initscr()獲取一個window對象代表全部屏幕。但是很多程序希望划分屏幕為幾個小的窗口,為了重繪,擦出這些工作在小窗口中獨立進行。newwin()函數就是用來新建一個新的窗口,需要給定窗口尺寸,並返回新的window對象的。

begin_x = 20; begin_y = 7
height = 5; width = 40
win = curses.newwin(height, width, begin_y, begin_x)

注意:坐標通過是先y后x。這和別的坐標系統不同,但是根深蒂固,寫的時候就這樣現在改太晚嘍。

當調用一個方法去顯示或者擦除文本時,效果不會立即顯示。 為了減少屏幕重繪的時間,curses就先累積這些操作,用一種更有效的方式去顯示。就比如說你的程序先在窗口顯示了幾個字符,然后就清除屏幕,那就沒必要發送初始字符了,因為它們不會被顯示。

因此,curses需要你使用refresh()函數明確指出重繪窗口。

pad

pad是window的特例。pad可以比顯示的屏幕大,一次只顯示pad的一部分。創建一個pad很簡單,只需要提供寬高即可。但是刷新pad需要提供屏幕上顯示的部分pad的坐標。

pad = curses.newpad(100, 100)
#  These loops fill the pad with letters; this is
# explained in the next section
for y in range(0, 100):
    for x in range(0, 100):
        try:
            pad.addch(y,x, ord('a') + (x*x+y*y) % 26)
        except curses.error:
            pass

#  Displays a section of the pad in the middle of the screen
pad.refresh(0,0, 5,5, 20,75)

同時由多個window或者多個pad,有一問題:刷新某個window或pad時屏幕會閃爍。

避免閃爍的方法:在每個window調用noutrefresh()方法。 然后使用refresh()方法的最后再調用doupdate()方法。

3、顯示文本

addscr不同格式如下:如果沒有坐標,字符顯示在上一次操作完的位置。

Form Description
str or ch Display the string str or character ch at the current position
str or ch, attr Display the string str or character ch, using attribute attr at the current position
y, x, str or ch Move to position y,x within the window, and display str or ch
y, x, str or ch, attr Move to position y,x within the window, and display str or ch, using attribute attr

屬性可以讓文本高亮顯示,比如黑體,下划線,倒序,彩色顯示。

4、屬性和顏色

屬性和描述:

Attribute Description
A_BLINK Blinking text
A_BOLD Extra bright or bold text
A_DIM Half bright text
A_REVERSE Reverse-video text
A_STANDOUT The best highlighting mode available
A_UNDERLINE Underlined text

屏幕第一行reverse-video顯示。

stdscr.addstr(0, 0, "Current mode: Typing mode",
              curses.A_REVERSE)
stdscr.refresh()

curses使用前景色和背景色,可通過color_pair()方法獲取一對顏色。

使用顏色對1顯示一行

stdscr.addstr("Pretty text", curses.color_pair(1))
stdscr.refresh()

start_color()初始化了8中基本顏色:0:black, 1:red, 2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white。

init_pair(n,f,b)修改顏色對n,讓f為前景色,b為背景色。顏色對0天生的黑白色,不允許改。

比如:修改color1為紅色文本,白色背景:

curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)

使用:

stdscr.addstr(0,0, "RED ALERT!", curses.color_pair(1))

5、用戶輸入

獲取輸入一遍使用getch()方法,這個方法暫停等待用戶輸入,顯示用echo()方法。

getch()返回一個整數 ,在0到255之間,表示輸入字符的ASCII值。打印255的是些特殊字符,比如Page Up,Home。

代碼經常這樣寫

while 1:
    c = stdscr.getch()
    if c == ord('p'):
        PrintDocument()
    elif c == ord('q'):
        break  # Exit the while()
    elif c == curses.KEY_HOME:
        x = y = 0

 getstr()獲取一個字符串。因為功能有限不常用。

curses.echo()            # Enable echoing of characters
# Get a 15-character string, with the cursor on the top line
s = stdscr.getstr(0,0, 15)

二、例子

代碼如下:

#-*- coding: UTF-8 -*-
import curses

stdscr = curses.initscr()

def display_info(str, x, y, colorpair=2):
    '''''使用指定的colorpair顯示文字'''  
    global stdscr
    stdscr.addstr(y, x,str, curses.color_pair(colorpair))
    stdscr.refresh()

def get_ch_and_continue():
    '''''演示press any key to continue'''
    global stdscr
    #設置nodelay,為0時會變成阻塞式等待
    stdscr.nodelay(0)
    #輸入一個字符
    ch=stdscr.getch()
    #重置nodelay,使得控制台可以以非阻塞的方式接受控制台輸入,超時1秒
    stdscr.nodelay(1)
    return True

def set_win():
    '''''控制台設置'''
    global stdscr
    #使用顏色首先需要調用這個方法
    curses.start_color()
    #文字和背景色設置,設置了兩個color pair,分別為1和2
    curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
    #關閉屏幕回顯
    curses.noecho()
    #輸入時不需要回車確認
    curses.cbreak()
    #設置nodelay,使得控制台可以以非阻塞的方式接受控制台輸入,超時1秒
    stdscr.nodelay(1)

def unset_win():
    '''控制台重置'''
    global stdstr
    #恢復控制台默認設置(若不恢復,會導致即使程序結束退出了,控制台仍然是沒有回顯的)
    curses.nocbreak()
    stdscr.keypad(0)
    curses.echo()
    #結束窗口
    curses.endwin()
if __name__=='__main__': try: set_win() display_info('Hola, curses!',0,5) display_info('Press any key to continue...',0,10) get_ch_and_continue() except Exception,e: raise e finally: unset_win()

執行:# python testcurses.py

三、排錯

報錯:

[root@yl-web-test srv]# python curses.py
Traceback (most recent call last):
  File "curses.py", line 2, in <module>
    import curses
  File "/srv/curses.py", line 4, in <module>
    stdscr = curses.initscr()
AttributeError: 'module' object has no attribute 'initscr'

原因:因為我的文件取名是curses.py,而系統也是用的curses.py,python執行時先從當前目錄查找,所以不能和系統文件重名。

換個名字,比如改名為testcurses.py 就好了。

參考:

https://docs.python.org/2/howto/curses.html

 

本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載注明出處:http://www.cnblogs.com/starof/p/4703820.html有問題歡迎與我討論,共同進步。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM