2013-02-15 14 views
6

我已經看到了Python中的進度條的不同解決方案,但簡單的標準輸出解決方案不適用於我的項目。我有多個類,並使用「日誌記錄」模塊輸出信息到STDOUT。我有一個函數,我想在一行顯示進度條,每次刷新緩衝區。簡單進度Python進度條直通日誌記錄模塊

例子:

for i in range(100): 
    time.sleep(1) 
    sys.stdout.write("\r%d%%" %i) 
    sys.stdout.flush() 

當我嘗試通過STDOUT寫,然後刷新緩衝區,或者緩衝區不沖洗或進度不會去任何地方。我希望避免某種線程或複雜的過程來實現這一點。有人有一個喜好的方式來做到這一點?

回答

0

如果你知道進度條總是寫入STDOUT,你應該只使用print而不是記錄器。查看文檔in the Python logging tutorial documentation

+0

使用「打印」的問題是,它將每個值都拋出一個新行,不再使輸出成爲進度條。 STDOUT應該刷新緩衝區並覆蓋現有的行,但在代碼中使用它時,這似乎不起作用。請注意,我並未在進度條代碼中包裝任何日誌模塊語法。 – 2013-02-15 15:38:53

+1

使用上面發佈的確切代碼,我看到輸出被替換。你是否在新行上看到每個號碼? – jknupp 2013-02-15 16:16:31

1

您可以使用tqdm progress bara custom handler through logging as described here

import logging 
import time 
import colorlog 
from tqdm import tqdm 

class TqdmHandler(logging.StreamHandler): 
    def __init__(self): 
     logging.StreamHandler.__init__(self) 

    def emit(self, record): 
     msg = self.format(record) 
     tqdm.write(msg) 

if __name__ == "__main__": 
    for x in tqdm(range(100)): 
     logger = colorlog.getLogger("MYAPP") 
     logger.setLevel(logging.DEBUG) 
     handler = TqdmHandler() 
     handler.setFormatter(colorlog.ColoredFormatter(
      '%(log_color)s%(name)s | %(asctime)s | %(levelname)s | %(message)s', 
      datefmt='%Y-%d-%d %H:%M:%S', 
      log_colors={ 
       'DEBUG': 'cyan', 
       'INFO': 'white', 
       'SUCCESS:': 'green', 
       'WARNING': 'yellow', 
       'ERROR': 'red', 
       'CRITICAL': 'red,bg_white'},)) 

     logger.addHandler(handler) 
     logger.debug("Inside subtask: "+str(x)) 
     time.sleep(.5) 
+0

它不適合我。我想,你可以試試這個: https://gist.github.com/w495/80f6a7351a10d5b6cecb5dad6c8cd8d6 – 2017-05-19 04:26:14

3

我解決了它這樣的:

import logging 
import time 
from tqdm import tqdm 
import io 

class TqdmToLogger(io.StringIO): 
    """ 
     Output stream for TQDM which will output to logger module instead of 
     the StdOut. 
    """ 
    logger = None 
    level = None 
    buf = '' 
    def __init__(self,logger,level=None): 
     super(TqdmToLogger, self).__init__() 
     self.logger = logger 
     self.level = level or logging.INFO 
    def write(self,buf): 
     self.buf = buf.strip('\r\n\t ') 
    def flush(self): 
     self.logger.log(self.level, self.buf) 

if __name__ == "__main__": 
    logging.basicConfig(format='%(asctime)s [%(levelname)-8s] %(message)s') 
    logger = logging.getLogger() 
    logger.setLevel(logging.DEBUG) 

    tqdm_out = TqdmToLogger(logger,level=logging.INFO) 
    for x in tqdm(range(100),file=tqdm_out,mininterval=30,): 
     time.sleep(.5) 

輸出

2016-12-19 15:35:06 [INFO ] 16%|#####9        | 768/4928 [07:04<40:50, 1.70it/s] 
2016-12-19 15:36:07 [INFO ] 18%|######6        | 865/4928 [08:04<40:34, 1.67it/s] 
+0

只是好奇在進度條'##### 9'結尾的數字來自哪裏,怎麼可以我們擺脫它? – Sam 2017-10-18 21:31:06

+0

我認爲它是16.9%和18.6%(小數點)。 – ddofborg 2017-10-19 07:25:44

2

我找不到很好的解決方案,所以我寫了enlighten progress bar來處理它。基本上,它會更改終端的滾動區域,以便日誌記錄在進度條上方完成,而不必在每次要寫入STDOUT時重新繪製進度條。這使您可以儘可能多地寫入終端,而無需修改logging,print等。

它應該可以在大多數非Windows終端上運行。 Windows支持可能會在未來出現,但沒有人要求它。

import logging 
import time 
import enlighten 

# Setup logging 
logging.basicConfig(level=logging.INFO) 
logger = logging.getLogger() 

# Setup progress bar 
manager = enlighten.get_manager() 
pbar = manager.counter(total=100, desc='Ticks', unit='ticks') 

for i in range(1, 101): 
    logger.info("Processing step %s" % i) 
    time.sleep(.2) 
    pbar.update() 
+0

我剛剛發現了這個模塊,正是我需要的!這次真是萬分感謝。 – 2018-01-20 16:59:27

相關問題