处理 Python 结构中的回车 (\r) 字符



我使用Python的Fabric通过ssh在远程主机上执行一些任务
当显示子任务的进度条时,其中一个任务在其输出中使用回车符。类似的东西:

int main(int argc, char* argv[]) {
        int i;
        for (i = 0; i <= 5; ++i) {
                printf("rProgress: %d%%", (int)(100 * ((float)i / 5)));
                fflush(stdout);
                sleep(1);
        }
        printf("n");
        return 0;
}

当这与python的Fabric:一起运行时

def some_task():
    with settings(user = 'root'):
        run('./task_with_progress_bar.out')
tasks.execute(some_task, hosts = ['server_name'])

Fabric将忽略r,而不是将进度条放在一行中,我得到的是:

[server_name] Executing task 'some_task'
[server_name] run: ./task_with_progress_bar.out
[server_name] out:
[server_name] out: Progress: 0%
[server_name] out: Progress: 20%
[server_name] out: Progress: 40%
[server_name] out: Progress: 60%
[server_name] out: Progress: 80%
[server_name] out: Progress: 100%
[server_name] out:

似乎r被当作n。。。

在上面的例子中,这还不错,但我正在运行的实际任务中充满了进度条,这些进度条以较小的步骤进行,这会用不必要的输出污染整个控制台。

有没有一种方法可以自定义输出,使Fabric不会忽略r,但仍然保持相同的通用格式:[<server_name>] <action_being_taken>?我喜欢这种格式,它整洁。

问题是结构正在n中转换r

解决这个问题的方法是创建一个类似文件的类,并将其作为stdout参数传递给run,这样我们就可以处理被调用程序产生的输出,并将n翻译回r。编写此类的挑战是确定哪些n必须翻译为r。以下是寻找"Progress:"来识别此类情况的尝试:

class FixProgress:
    def __init__(self):
        self.saw_progress = False
    def write(self, s):
        if 'Progress:' in s:
            self.saw_progress = True
        if s == 'n' and self.saw_progress:
            sys.stdout.write('r')
            self.saw_progress = False
        else:
            sys.stdout.write(s)
    def flush(self):
        sys.stdout.flush()
def some_task():
    with settings(user = 'root'):
        run('./task_with_progress_bar.out', stdout = FixProgress())

这对问题中的c程序来说是正确的。

如果可以更改输出进度条的c文件的源代码,则可以使用isatty()测试stdin是否为tty。如果为false,则可以抑制进度条输出,使其仅以特定值更新,即间隔25。

http://linux.die.net/man/3/isatty

最新更新