How to create a progress bar to a file instead of sys.stderr, using the logging module?
Author: evandrocoanCreated May 13, 2019Updated Sep 8, 2026
Labelsquestion/docs ‽
- I have visited the [source website], and in particular read the [known issues]
- I have searched through the [issue tracker] for duplicates
- I have mentioned version numbers, operating system and
environment, where applicable:
import tqdm, sys print(tqdm.__version__, sys.version, sys.platform) # 4.23.4 3.7.2 (default, Jan 2 2019, 17:07:39) [MSC v.1915 64 bit (AMD64)] win32
This example works fine for a stream handler to sys.stderr:
import sys
import tqdm
import time
import logging
class DummyTqdmFile(object):
file = None
def __init__(self, file):
self.file = file
def write(self, x):
# Avoid print() second call (useless \n)
if len( x.rstrip() ) > 0:
tqdm.tqdm.write( x, file=self.file, end='' )
def flush(self):
return getattr( self.file, "flush", lambda: None )()
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, stream=DummyTqdmFile(sys.stderr))
log = logging.getLogger(__name__)
log.info("loop")
# for x in tqdm.trange(1, 101, mininterval=10):
for x in tqdm.trange(1, 10):
time.sleep(1.2)
if not x % 5:
log.debug("in loop %d\nnew line" % x)
log.info("done")But, what if I am logging to a file like /var/log/myfile.log?
If I change the logger setup line to this:
logging.basicConfig(level=logging.DEBUG, filename='myfile.log')The progress bar is printed to the sys.stderr, not in the file myfile.log.
I tried this variation:
import sys
import tqdm
import time
import logging
class DummyTqdmFile(object):
file = None
def __init__(self, file):
self.file = file
def write(self, x):
# Avoid print() second call (useless \n)
if len( x.rstrip() ) > 0:
tqdm.tqdm.write( x, file=self.file, end='' )
def flush(self):
return getattr( self.file, "flush", lambda: None )()
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, filename='myfile.log')
log = logging.getLogger(__name__)
logging.root.handlers[0].stream = DummyTqdmFile(logging.root.handlers[0].stream)
log.info("loop")
# for x in tqdm.trange(1, 101, mininterval=10):
for x in tqdm.trange(1, 10, file=logging.root.handlers[0].stream):
time.sleep(1.2)
if not x % 5:
log.debug("in loop %d\nnew line" % x)
log.info("done")It almost worked right, running it, it outputs this to the file:
INFO:__main__:loop
0%| | 0/9 [00:00<?, ?it/s]
11%|# | 1/9 [00:01<00:09, 1.20s/it]
22%|## | 2/9 [00:02<00:08, 1.20s/it]
33%|### | 3/9 [00:03<00:07, 1.20s/it]
44%|#### | 4/9 [00:04<00:06, 1.20s/it]DEBUG:__main__:in loop 5
new line
56%|##### | 5/9 [00:06<00:04, 1.20s/it]
67%|###### | 6/9 [00:07<00:03, 1.20s/it]
78%|####### | 7/9 [00:08<00:02, 1.20s/it]
89%|######## | 8/9 [00:09<00:01, 1.20s/it]
100%|##########| 9/9 [00:10<00:00, 1.20s/it]INFO:__main__:doneBut, it is missing a new line after each progress bar, i.e., it should output this:
INFO:__main__:loop
0%| | 0/9 [00:00<?, ?it/s]
11%|# | 1/9 [00:01<00:09, 1.20s/it]
22%|## | 2/9 [00:02<00:08, 1.20s/it]
33%|### | 3/9 [00:03<00:07, 1.20s/it]
44%|#### | 4/9 [00:04<00:06, 1.20s/it]
DEBUG:__main__:in loop 5
new line
56%|##### | 5/9 [00:06<00:04, 1.20s/it]
67%|###### | 6/9 [00:07<00:03, 1.20s/it]
78%|####### | 7/9 [00:08<00:02, 1.20s/it]
89%|######## | 8/9 [00:09<00:01, 1.20s/it]
100%|##########| 9/9 [00:10<00:00, 1.20s/it]
INFO:__main__:doneSource: tqdm/tqdm