Spaces:
Running
Running
File size: 6,309 Bytes
33ba306 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | import sys
class Progress(object):
def __init__(self,
first: int = 1, # the initial iteration
last: int = 10, # the final iteration
string: str = 'Processing iteration', # the string prefix that is returned
fraction: bool = True, # whether to output the fraction of things completed
rng: bool = False, # whether to output the range that the iterations span
percent: bool = True, # whether to show percent completion
hash: bool = False, # whether to have a hash bar for progress
hashnum: int = 20, # width of the hash progress bar
endmsg: str = 'DONE', # end message
writeevery: int = 1, # write output every n calls
):
"""
A progress output object for use when performing a large number of
repititions of the same process and informing the user of progress
is desired.
:param first: The first iteration of the process.
:param last: The last iteration of the process.
:param string: The string prefix that is written (this is usually information about
the process.
:param fraction: Whether the fractional progress should be written in the printed string. e.g. 1/10.
:param rng: Whether the iteration range should be written in the printed string.
e.g. (1-10)
:param percent: Whether the percent progress should be written in the printed string.
e.g. 10.0%
:param hash: Whether a hash-type progress bar should be written in the printed
string. e.g. |##### | Default: False
:param hashnum: If *hashes* is True, this is the width of the hash-type progress bar.
:param endmsg: The message that is printed when the `fin()` method is called.
:param writeevery: Write an output every n calls. This can be used if an iteration is
rapid and printing every output is not particularly useful.
**Examples**
::
>>> prog = Progress()
>>> prog.write(1)
Processing iteration #1/10 0.0%
>>> prog.write(7)
Processing iteration #7/10 66.7%
>>> for i in range(1,11):
prog.write(i)
prog.fin()
Processing iteration #10/10 100.0% DONE
"""
self.first = first
self.last = last
self.string = string
self.fraction = fraction
self.rng = rng
self.percent = percent
self.hash = hash
self.hashnum = hashnum
self.endmsg = endmsg
self.writeevery = writeevery
self.wr = sys.stdout.write
self.fl = sys.stdout.flush
self.count = 0
self.strlen = 0
self.current = 0 # current state
self.spinner = ['|', '/', '-', '\\']
def __str__(self):
"""returns the progress string at the current iteration"""
return self.write(self.current, True)
def __repr__(self):
return f'{self.__class__.__name__}({self.string} {self.first}-{self.last})'
def __getitem__(self, x):
"""
Prints and returns the progress string at iteration x
This accomplishes the same thing as write()
"""
return self.write(x)
@property
def perc(self):
try:
return round(
(float(self.current) - self.first)
/ float(self.last - self.first)
* 100.,
1
)
except ZeroDivisionError:
return 0.
def write(self, current, suppress=False):
"""
Writes the progress of the iteration
:param current: current iteration
:param suppress: suppress output
:return: formatted output string
"""
self.count += 1 # keep count
if self.writeevery != 1:
# if the counter does not match the write, bail out
if self.count != self.last and self.count % self.writeevery != 0:
return None
self.current = current # saves the current state
string = f'{self.string}' # begin the string
if self.fraction is True:
string += f' #{current - self.first + 1}/{self.last - self.first + 1}'
if self.rng is True:
string += f' ({self.first}-{self.last})'
if self.percent is True:
string += f' {self.perc}%'
if self.hash is True:
string += self.hashes()
# create space filler if output has somehow shrunk below the length of the previous output
if len(string) < self.strlen:
string += ' ' * (self.strlen - len(string))
self.strlen = len(string)
# does not write string to terminal, instead returns the generated progress string
if suppress is True:
return string
try:
self.wr(f'\r{string}')
# a catch for I/O errors that sometimes pop up for large iteration processes
except ValueError:
pass
return string
def hashes(self):
"""generates the hash-type progress bar if called for"""
out = ' |'
num = int(self.perc / 100. * self.hashnum)
out += '#' * num # add completed
if num < self.hashnum: # add spinner
out += self.spinner[self.count % 4]
out += ' ' * (self.hashnum - len(out) + 2) # add still to go
out += '|'
return out
def fin(self, msg=None):
"""
writes the completion message of the object and starts a new line
if msg is specified, that message will be written instead of the object's
completion message
"""
if msg is None:
msg = self.endmsg
self.wr(f' {msg}\n')
self.fl() # flush output
if __name__ == '__main__': # for testing and troubleshooting
first = 1
finish = 255
prog = Progress(
first=first,
last=finish,
# hashes = True,
)
import time
for i in range(first, finish + 1):
prog.write(i)
time.sleep(0.01)
prog.fin()
|