首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python“呈现”文本,如终端模拟器

Python“呈现”文本,如终端模拟器
EN

Stack Overflow用户
提问于 2019-07-01 13:35:44
回答 1查看 44关注 0票数 1

我目前正在编写一个用于我的研究的一套工具。其中一种工具是在长时间运行的进程终止或停止时自动发送通知的方法。这些消息可以是电子邮件,并且可以捕获代码块(例如(或更多的例子))产生的输出:

代码语言:javascript
复制
>>> stream = io.StringIO()
>>> notify = NotifyViaStream("testtask", stream)
>>> # set a custom template used to stringify the notifications
>>> notify.notification_template = "{task} {reason} {output}"
>>> with notify.when_done():
...     # potentially long-running process
...     print('testoutput')
>>> stream.getvalue()
'testtask done testoutput'

我现在试图解决的问题是,特别是长时间运行的任务,比如打印进度条来通知用户当前的状态。因此,他们通常使用\r回车将光标移动到行的开头,并覆盖整行以更新进度条。然而,当发送(文本)电子邮件时,这一封闭式输出(包含\r的意志当然不会像这样呈现)。相反,每次更新都会在新行中打印,从而导致混乱的输出,例如:

代码语言:javascript
复制
running RTEDataset fs=(3, 4, 5), nb_f=128
Epoch 1/3

 1/77 [..............................] - ETA: 8:12 - loss: 1.0988 - acc: 0.3750                                                                               
 2/77 [..............................] - ETA: 4:21 - loss: 0.9525 - acc: 0.5156                                                                               
 3/77 [>.............................] - ETA: 3:03 - loss: 0.8636 - acc: 0.5625                                                                               
 4/77 [>.............................] - ETA: 2:24 - loss: 0.9153 - acc: 0.5312                                                                               
 5/77 [>.............................] - ETA: 2:01 - loss: 0.9294 - acc: 0.5250                                                                               
 6/77 [=>............................] - ETA: 1:45 - loss: 0.9078 - acc: 0.5417                                                                               
 7/77 [=>............................] - ETA: 1:33 - loss: 0.9101 - acc: 0.5268 
 ... and so on 

在终端模拟器上“预渲染”输出的最佳方法是什么?是否有更明智的方法,只使用regex来匹配从行开始到\r的所有内容,并将其替换为空字符串?如果下一行不完全覆盖最后一行,例如:

test\routput\rback将在终端上作为backut打印,但使用这种简单的方法作为back打印。

有没有一种不使用外部库(可能使用ncursed,甚至在电子邮件客户端的客户端)来实现这一目标的pythonic方法?

额外的问题:您是否会将行为配置为显式不处理(甚至删除)回车返回?如果是的话,您的首选默认值是什么?

EN

回答 1

Stack Overflow用户

发布于 2019-07-03 08:48:35

好的,所以我在标准库中找不到任何东西,所以我编写了这个函数,它完全满足了我的需要:

代码语言:javascript
复制
def render_text(text: str, maxwidth: int = -1) -> str:
    r"""
    Attempt to render a text like an (potentiall infinitely wide)
    terminal would.

    Thus carriage-returns move the cursor to the start of
    the line, so subsequent characters overwrite the previous.

    .. doctest::

        >>> render_text('asd\rbcd\rcde\r\nqwe\rert\n123', maxwidth=2)
        'cd\ne \ner\nt \n12\n3'

    :param text: Input text to render
    :param maxwidth: if > 0, wrap the text to the specified maximum length
        using the textwrapper library
    """
    # create a buffer for the rendered ouput text
    outtext = StringIO()
    for char in text:
        if char == "\r":
            # seek to one character past the last new line in
            # the current rednered text. This woks nicely because
            # rfind will return -1 if no newline is found this
            # this will seek to the beginning of the stream
            outtext.seek(outtext.getvalue().rfind("\n") + 1)

            # continue to the next character, dont write he carriage return
            continue
        elif char == "\n":
            # a newline moves the cursor to the end of he buffer
            # the newline itself is written below
            outtext.seek(len(outtext.getvalue()))

        # write he current character to the buffer
        outtext.write(char)

    rendered_text = outtext.getvalue()

    # connditionnally wrap the text after maxwidth characters
    if maxwidth > 0:
        rendered_text = textwrap.fill(rendered_text, maxwidth)
    return rendered_text

您可以复制此代码或在我的框架中的io模块中使用我的实现。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56836672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档