【问题标题】:colour terminal libraries彩色终端库
【发布时间】:2011-11-27 13:53:04
【问题描述】:

我正在尝试在 Python 中对我的文本实现颜色循环...由于上下文发生了巨大变化,该问题已被编辑并作为另一个问题重新提交。请改用here

这个问题更多的是关于我应该使用什么库 - termcolorcoloramacursesansi colour recipe

到目前为止的代码:

#!/usr/bin/env python

'''
        "arg" is a string or None
        if "arg" is None : the terminal is reset to his default values.
        if "arg" is a string it must contain "sep" separated values.
        if args are found in globals "attrs" or "colors", or start with "@" \
    they are interpreted as ANSI commands else they are output as text.
        @* commands:

            @x;y : go to xy
            @    : go to 1;1
            @@   : clear screen and go to 1;1
        @[colour] : set foreground colour
        ^[colour] : set background colour

        examples:
    echo('@red')                  : set red as the foreground color
    echo('@red ^blue')             : red on blue
    echo('@red @blink')            : blinking red
    echo()                       : restore terminal default values
    echo('@reverse')              : swap default colors
    echo('^cyan @blue reverse')    : blue on cyan <=> echo('blue cyan)
    echo('@red @reverse')          : a way to set up the background only
    echo('@red @reverse @blink')    : you can specify any combinaison of \
            attributes in any order with or without colors
    echo('@blink Python')         : output a blinking 'Python'
    echo('@@ hello')             : clear the screen and print 'hello' at 1;1

colours:
{'blue': 4, 'grey': 0, 'yellow': 3, 'green': 2, 'cyan': 6, 'magenta': 5, 'white': 7, 'red': 1}

    '''

'''
    Set ANSI Terminal Color and Attributes.
'''
from sys import stdout
import random
import sys
import time

esc = '%s['%chr(27)
reset = '%s0m'%esc
format = '1;%dm'
fgoffset, bgoffset = 30, 40
for k, v in dict(
    attrs = 'none bold faint italic underline blink fast reverse concealed',
    colours = 'grey red green yellow blue magenta cyan white'
).items(): globals()[k]=dict((s,i) for i,s in enumerate(v.split()))

def echo(arg=None, sep=' ', end='\n', rndcase=True, txtspeed=0.03):

    cmd, txt = [reset], []
    if arg:
        # split the line up into 'sep' seperated values - arglist
            arglist=arg.split(sep)

        # cycle through arglist - word seperated list 
            for word in arglist:

                if word.startswith('@'):
            ### First check for a colour command next if deals with position ###
                # go through each fg and bg colour  
                tmpword = word[1:]
                    if tmpword in colours:
                        cmd.append(format % (colours[tmpword]+fgoffset))
                    c=format % attrs[tmpword] if tmpword in attrs else None
                    if c and c not in cmd:
                                cmd.append(c)
                    stdout.write(esc.join(cmd))
                    continue
                # positioning (starts with @)
                word=word[1:]
                if word=='@':
                    cmd.append('2J')
                    cmd.append('H')
                    stdout.write(esc.join(cmd))
                    continue
                else:
                    cmd.append('%sH'%word)
                    stdout.write(esc.join(cmd))
                    continue

                if word.startswith('^'):
            ### First check for a colour command next if deals with position ###
                # go through each fg and bg colour  
                tmpword = word[1:]
                    if tmpword in colours:
                        cmd.append(format % (colours[tmpword]+bgoffset))
                    c=format % attrs[tmpword] if tmpword in attrs else None
                    if c and c not in cmd:
                                cmd.append(c)
                    stdout.write(esc.join(cmd))
                    continue                    
            else:
                for x in word:  
                    if rndcase:
                        # thankyou mark!
                        if random.randint(0,1):
                                x = x.upper()
                        else:
                            x = x.lower()
                    stdout.write(x)
                    stdout.flush()
                    time.sleep(txtspeed)
                stdout.write(' ')
                time.sleep(txtspeed)
    if txt and end: txt[-1]+=end
    stdout.write(esc.join(cmd)+sep.join(txt))

if __name__ == '__main__':

    echo('@@') # clear screen
    #echo('@reverse') # attrs are ahem not working
    print 'default colors at 1;1 on a cleared screen'
    echo('@red hello this is red')
    echo('@blue this is blue @red i can ^blue change @yellow blah @cyan the colours in ^default the text string')
    print
    echo()
    echo('default')
    echo('@cyan ^blue cyan blue')
#   echo('@cyan ^blue @reverse cyan blue reverse')
#   echo('@blue ^cyan blue cyan')
    #echo('@red @reverse red reverse')
#    echo('yellow red yellow on red 1')
#    echo('yellow,red,yellow on red 2', sep=',')
#    print 'yellow on red 3'

#        for bg in colours:
#                echo(bg.title().center(8), sep='.', end='')
#                for fg in colours:
#                        att=[fg, bg]
#                        if fg==bg: att.append('blink')
#                        att.append(fg.center(8))
#                        echo(','.join(att), sep=',', end='')

    #for att in attrs:
    #   echo('%s,%s' % (att, att.title().center(10)), sep=',', end='')
    #   print

    from time import sleep, strftime, gmtime
    colist='@grey @blue @cyan @white @cyan @blue'.split()
    while True:
        try:
            for c in colist:
                sleep(.1)
                echo('%s @28;33 hit ctrl-c to quit' % c,txtspeed=0)
            #echo('@yellow @6;66 %s' % strftime('%H:%M:%S', gmtime()))
        except KeyboardInterrupt:
            break
        except:
            raise
    echo('@10;1')
    print

【问题讨论】:

  • 一个快速观察是 \e 应该是 \033 就像你的第一个 BOLD 定义一样。
  • (a) 如果你去实现你自己的,你就是在重复别人已经完成的工作,并确保他们已经正确地完成了。 (b) 当你可以使用他们已经成功实施的东西时,为什么你甚至再去做这项工作? (当然,我自己也做过,但这无关紧要!) (c) 如果您关心 Windows,甚至不要尝试自己编写;使用颜色。
  • 啊不,我根本不关心 Windows。猜猜我问的主要原因是 - 我是否能够使用一些库并且在一次打印一个字符的东西中仍然可以轻松地工作。如果我必须实现自己的代码来做到这一点,那么使用外部资源就没有多大意义了。加上这意味着安装额外的代码来运行。是的 :) 它也是为了练习,现在只用了一周多的时间在做 python。
  • 什么你只是去标记重复而不阅读帖子? :) 我实际上知道那个页面,但这不是我的问题,问题源于一次打印一个字符。好吧,如果没有人建议我将我笨重的 bash 例程复制到 python 中然后回发……也许有人也想要这个。

标签: python colors


【解决方案1】:

这里有一些技巧可以尝试:

  1. 此代码块创建实际转义字符串的列表。它使用list comprehension 来遍历颜色名称列表并在colour 字典中查找转义码。 .split() 只是一种无需输入大量引号-逗号-引号序列即可创建字符串列表的懒惰方式。

    color_cycle = [
        [colour[name] for name in 'bldylw bldred bldgrn bldblu txtwht'.split()],
        [colour[name] for name in 'txtblu txtcyn'.split()]
    ]
    
  2. 稍后,您的函数可以通过创建iterator 来使用这些列表。这个特定的迭代器使用标准库函数itertools.cycle,它无限地重复一个序列。我在这里假设你想用不同的颜色写字符串的每个字符。

    import itertools
    
    # Create an iterator for the selected color sequence.
    if colourc:
        icolor = itertools.cycle(color_cycle[colourc - 1])
    
    for a in stringy:
        # Write out the escape code for next color
        if colourc:
            color = next(icolor)
            sys.stdout.write(color)
    
  3. 这是另一种选择随机大小写的方法。在 Python 中,零被认为是错误的:

        if rndcase:
            if random.randint(0,1):
                a = a.upper()
            else:
                a = a.lower()
    

【讨论】:

  • 哦,你的美女。不幸的是不能感谢你。啤酒和杯子蛋糕给你。到目前为止,我遇到过几次列表推导,但它们对我来说是全新的,有点混淆了循环中的所有这些循环。零是假的!什么 !我以为是真的!我确定它在 bash 中是真的,太好了,让它难以记住的方式:) 我真的不明白 2) 我必须破解它,看看它是否沉入其中,但是 3) 这种方式比我做的更快吗?我查看了随机函数,并假设在两件事之间进行直接选择会比其他事情更快。
  • 在 Python 中,零个空字符串、空列表、空字典……对于 if,所有这些都被认为是错误的。投票和绿色检查就足够了(wink)。
  • 课程。是的,非常感谢,我玩这些概念玩得很开心,我把它放在这里,以防有人和我一样痴迷。啊,我在想 bash 退出代码。
  • 如果您还没有找到该站点,可以查看diveintopython.net
  • 深入Python?我把头撞到了底部!
【解决方案2】:

这里有几个问题。首先,为什么在 colourc 变量上使用 0 和 1 而不是 TrueFalse?如果您使用正确的布尔值, 更容易判断正在发生的事情。

在第一个 if 块中,如果 colourc 不为 0,则将整个字符串写入标准输出。我很惊讶这实际上并没有像我运行代码时那样打印颜色。

每次打印一个字符时,这就是您的代码出现问题的地方。 ANSI 转义序列不是单个字符,不能这样对待。 一方面,您的随机大小写代码可以通过随机大写或小写序列中的 m 或 K 字符来破坏它碰巧遇到的任何 ANSI 序列。

当我使用rndcase=False 运行您的代码时,即使是一次代码中的单个字符也可以正常工作。

您应该重新考虑如何在输入中设置颜色,以便当新颜色生效时,您可以打印整个 ANSI 序列,然后是输出中的下一个字符。

【讨论】:

  • 首先,感谢您花时间回答。回复:布尔值,我没想到。我认为主要原因是因为我不知道我在做什么:) 对不起,我以为你的意思是随机位。啊我这样做的原因是因为我可能有任意数量的颜色序列。第一点只是为了测试我没有设法开始工作的彩色打印,它只是将转义码打印到终端。是的,它必须识别转义序列。我试图破解食谱链接,但无法理解它在做什么。
  • 所以要澄清 0 将被关闭,其他任何东西都是颜色循环序列的数量。
猜你喜欢
  • 2011-07-22
  • 2015-07-15
  • 1970-01-01
  • 2013-01-18
  • 2021-07-18
  • 2011-09-18
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
相关资源
最近更新 更多