我目前正在编写一个用于我的研究的一套工具。其中一种工具是在长时间运行的进程终止或停止时自动发送通知的方法。这些消息可以是电子邮件,并且可以捕获代码块(例如(或更多的例子))产生的输出:
>>> 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的意志当然不会像这样呈现)。相反,每次更新都会在新行中打印,从而导致混乱的输出,例如:
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方法?
额外的问题:您是否会将行为配置为显式不处理(甚至删除)回车返回?如果是的话,您的首选默认值是什么?
发布于 2019-07-03 08:48:35
好的,所以我在标准库中找不到任何东西,所以我编写了这个函数,它完全满足了我的需要:
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模块中使用我的实现。
https://stackoverflow.com/questions/56836672
复制相似问题