2015-11-05 6 views
0

У меня есть вывод, который я бы хотел написать, и у меня есть простая функция Python, которая выполняет это для меня (в терминале на OS X), но я не уверен, могу ли я полагаться на нее вообще :Надежная надпечатка вывода из Python

import sys 
import time 

def print_over(s): 
    print(s, end='\r') 
    print("\033[F" * (s.count('\n')+1)) 
    sys.stdout.flush() 
    time.sleep(0.2) 

Я понимаю, что там будут какие-то контексты, где это не будет работать, конечно, но интересно

  • насколько широко можно ожидать, что она работает (например, это просто какой-то бзик OS X, что позволяет это),
  • как охарактеризовать где он будет работать и не будет работать (например, есть ли какой-либо POSIX или другой стандарт, который гарантирует, что он будет), и
  • могу ли я определить из моего кода, будет ли он работать.
+0

Он не будет работать в Windows. –

+0

@MarkRansom: Есть что-нибудь, что может заставить что-то подобное работать в Windows? – orome

+0

http://stackoverflow.com/a/517207/4023997 – ZN13

ответ

1

Игнорирование обсуждение переносимости Microsoft Console API (что OP может исследовать), и просто сосредоточиться на тех местах, где «ANSI-ускользает» работа:

Эта линия представляет особый интерес, так как это единственный последовательность выхода используется:

print("\033[F" * (s.count('\n')+1)) 

Это соответствует ECMA-48 управления CPL, например, как в XTerm Control Sequences:

CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL). 
  • ОП спросил «насколько широко можно ожидать, что она работает». Это зависит. Он реализован в xterm (и Terminal.app реализует справедливую часть этого), но не был частью VT100 или VT220 (см. Документацию по адресу http://vt100.net). Он был добавлен в xterm в 1996. Поэтому считайте, что это ограничено программами, имитирующими xterm.

  • POSIX нечего сказать по этой теме. X/Open Curses (не входит в POSIX) закрывается —, но CPL не соответствует ни одному из возможностей terminfo. ECMA-48 имеет значение, но нет гарантии, что любая функция, перечисленная в ECMA-48, реализована на любом данном терминале. Скорее, он перечисляет возможности и предписывает их синтаксис. Также нет никакой гарантии, что любая данная функция xterm находится в другой программе (см., Например, Comparing versions, by counting controls).

  • В принципе, можно было бы попытаться использовать отчет курсора позиции (последовательность управления CPR), чтобы увидеть, где находится курсор после использования CPL, но даже это ненадежно на некоторых «XTERM эмуляторов».

Кстати, последовательность управления CPL принимает повторный-параметр, поэтому оператор печати может быть переписан, чтобы использовать, что (а не повторять последовательность управления).

Если вы хотите, чтобы быть немного более портативными, используя CUU (курсор вверх) управление работает с VT100, и (как CPL) может быть настроен параметрами с повторным подсчетом.То есть "\033[A":

CSI Ps A Cursor Up Ps Times (default = 1) (CUU). 
0

Почему не использовать curses? Он работает в Linux, OSX и теперь есть Windows implementation (как сообщается here).

Следующий пример будет надежным на большинстве платформ:

from curses import wrapper 
import time 

def print_over(scr, s): 
    scr.clear() 
    scr.addstr(5, 0, s) 
    scr.refresh() 

def main(scr): 
    for i in range(10, 110, 10): 
     print_over(scr,'Progress: %d %%'%i) 
     time.sleep(1) 

wrapper(main) 

EDIT:

Вот еще один пример, который не очищает весь экран:

from curses import tparm, tigetstr, setupterm 
import time 

def tput(cmd, *args): 
    print (tparm(tigetstr(cmd), *args), end='') # Emulates Unix tput 

class window(): 
    def __init__(s, x, y, w, h): 
     s.x, s.y, s.w, s.h = x, y, w, h # store window coordinates and size 

    def __enter__(s): 
     tput('sc') # saves current cursor position 
     s.clear() # clears the window 
     return s 

    def __exit__(s, exc_type, exc_val, exc_tb): 
     tput('rc') # restores cursor position 

    def clear(s, fill=' '): 
     for i in range(s.h): 
      tput('cup', s.y+i, s.x) # moves cursor to the leftmost column 
      print (fill*s.w, end='') 

    def print_over(s, msg, x, y): 
     tput('cup', s.y+y, s.x+x) 
     print (msg, end='') 

setupterm() 
with window(x=5, y=10, w=80, h=5) as w: 
    for i in range(10, 110, 10): 
     w.clear() 
     w.print_over('Progress: %d %%'%i, 5, 2) 
     time.sleep(1) 

А вот другой один, который переписывает только последнюю строку:

from curses import tparm, tigetstr, setupterm 
import time 

def tput(cmd, *args): 
    print (tparm(tigetstr(cmd), *args), end='') # Emulates Unix tput 

setupterm() 
for i in range(10, 110, 10): 
    tput('el') # clear to end of line 
    print (' Progress: %d %%'%i, end='\r') 
    time.sleep(1) 

В принципе, принцип всегда заключается в использовании curses с tput commands, чтобы избежать явных escape-символов.

Обратите внимание, что вам может потребоваться сброс stdout или просто запуск сценария с помощью python -u.

+0

Если он использует проклятия, он использует весь экран. Некоторые люди хотят, чтобы приложение из командной строки просто использовало несколько строк. –

+0

@ThomasDickey: Правильно, вот что я ищу. – orome