Python’s `str.format()`, fill characters, and ANSI colors

丶灬走出姿态 提交于 2020-06-24 08:39:17

问题


In Python 2, I’m using str.format() to align a bunch of columns of text I’m printing to a terminal. Basically, it’s a table, but I’m not printing any borders or anything—it’s simply rows of text, aligned into columns.

  • With no color-fiddling, everything prints as expected.
  • If I wrap an entire row (i.e., one print statement) with ANSI color codes, everything prints as expected.
  • However: If I try to make each column a different color within a row, the alignment is thrown off. Technically, the alignment is preserved; it’s the fill characters (spaces) that aren’t printing as desired; in fact, the fill characters seem to be completely removed.

I’ve verified the same issue with both colorama and xtermcolor. The results were the same. Therefore, I’m certain the issue has to do with str.format() not playing well with ANSI escape sequences in the middle of a string.

But I don’t know what to do about it! :( I would really like to know if there’s any kind of workaround for this problem.

Color and alignment are powerful tools for improving readability, and readability is an important part of software usability. It would mean a lot to me if this could be accomplished without manually aligning each column of text.

Little help? ☺


回答1:


Python doesn't distinguish between 'normal' characters and ANSI colour codes, which are also characters that the terminal interprets.

In other words, printing '\x1b[92m' to a terminal may change the terminal text colour, Python doesn't see that as anything but a set of 5 characters. If you use print repr(line) instead, python will print the string literal form instead, including using escape codes for non-ASCII printable characters (so the ESC ASCII code, 27, is displayed as \x1b) to see how many have been added.

You'll need to adjust your column alignments manually to allow for those extra characters.

Without your actual code, that's hard for us to help you with though.




回答2:


This is a very late answer, left as bread crumbs for anyone who finds this page while struggling to format text with built-in ANSI color codes.

byoungb's comment about making padding decisions on the length of pre-colorized text is exactly right. But if you already have colored text, here's a work-around:

See my ansiwrap module on PyPI. Its primary purpose is providing textwrap for ANSI-colored text, but it also exports ansilen() which tells you "how long would this string be if it didn't contain ANSI control codes?" It's quite useful in making formatting, column-width, and wrapping decisions on pre-colored text. Add width - ansilen(s) spaces to the end or beginning of s to left (or respectively, right) justify s in a column of your desired width. E.g.:

def ansi_ljust(s, width):
    needed = width - ansilen(s)
    if needed > 0:
        return s + ' ' * needed
    else:
        return s

Also, if you need to split, truncate, or combine colored text at some point, you will find that ANSI's stateful nature makes that a chore. You may find ansi_terminate_lines() helpful; it "patch up" a list of sub-strings so that each has independent, self-standing ANSI codes with equivalent effect as the original string.

The latest versions of ansicolors also contain an equivalent implementation of ansilen().



来源:https://stackoverflow.com/questions/14140756/python-s-str-format-fill-characters-and-ansi-colors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!