如何打印多行,让后续行独立替换每一行 (Python)
How can I print multiple lines, having subsequent lines replacing each of them independently (Python)
我正在运行使用多处理模块中的 Pool
对象并行工作的程序。
我想做的是 运行 一个函数并行 n 次,每次都有一个单独的加载百分比,我希望它更新每个函数的百分比而不替换其他百分比... 示例:
f(x):
while x < 0:
print 'For x = {0}, {1}% completed...\r'.format(x, percentage),
而且我会 运行 并行多次执行该函数。
我想要实现的效果如下,f(10000000), f(15000000), f(7000000):
For x = 10000000, 43% completed
For x = 15000000, 31% completed
For x = 7000000, 77% completed
并且百分比将在各自的行中更新而不替换 x 的其他值,在此函数 f
中将同时 运行ning 三次。
我尝试使用回车 return '\r' 但这会替换每一行并且只会造成混乱。
感谢您抽出宝贵时间阅读本文post!希望你能告诉我。
我正在使用 Python 2.7,但如果它只能通过 Python 3 实现,我愿意接受建议。
诅咒
正如@Keozon 在评论中提到的,实现这一目标的一种方法是使用 curses 库。
python 网站上有一个 good guide for curses。
ANSI 转义码
或者,您可以尝试使用 ANSI escape codes 来移动光标。
这在 Python3 中,但它在任何版本中都可以正常工作,您只需要更改周围的打印语句(或 from __future__ import print_function
)。
print('Hello')
print('World')
print('3[F3[F3[K', end='') # Up, Up, Clear line
# Cursor is at the 'H' of 'Hello'
print('Hi') # Overwriting 'Hello'
# Cursor is at the 'W' of 'World'
print('3[E', end='') # Down
# Cursor is on the blank line after 'World'
print('Back to the end')
输出:
Hi
World
Back to the end
编辑:
我在这里为你做了太多的工作,但是嘿,这里基本上是一个使用我上面提到的 ANSI 方法的完整解决方案:
import time
import random
class ProgressBar:
def __init__(self, name):
self._name = name
self._progress = 0
@property
def name(self):
return self._name
def get_progress(self):
"""
Randomly increment the progress bar and ensure it doesn't go
over 100
"""
self._progress += int(random.random()*5)
if self._progress > 100:
self._progress = 100
return self._progress
class MultipleProgressBars:
def __init__(self, progress_bars):
self._progress_bars = progress_bars
self._first_update = True
self._all_finished = False
@property
def all_finished(self):
"""
A boolean indicating if all progress bars are at 100
"""
return self._all_finished
def update(self):
"""
Update each progress bar
"""
# We don't want to move up and clear a line on the first run
# so we have a flag to make sure this only happens on later
# calls
if not self._first_update:
# Move up and clear the line the correct number of times
print('3[F3[K'*len(self._progress_bars),end='', sep='')
num_complete = 0 # Number of progress bars complete
for progress_bar in self._progress_bars:
name = progress_bar.name
progress = progress_bar.get_progress()
if progress == 100:
num_complete += 1
# Print out a progress bar (scaled to 40 chars wide)
print(
name.ljust(10),
'[' + ('='*int(progress*0.4)).ljust(40) + ']',
str(progress)+'%')
if num_complete == len(self._progress_bars):
self._all_finished = True
self._first_update = False # Mark the first update done
# Create a list of ProgressBars and give them relevant names
progress_bars = [
ProgressBar('James'),
ProgressBar('Bert'),
ProgressBar('Alfred'),
ProgressBar('Frank')
]
# Create a new instance of our MultipleProgressBars class
mpb = MultipleProgressBars(progress_bars)
# Keep updating them while at least one of them is still active
while not mpb.all_finished:
mpb.update()
time.sleep(0.2)
我正在运行使用多处理模块中的 Pool
对象并行工作的程序。
我想做的是 运行 一个函数并行 n 次,每次都有一个单独的加载百分比,我希望它更新每个函数的百分比而不替换其他百分比... 示例:
f(x):
while x < 0:
print 'For x = {0}, {1}% completed...\r'.format(x, percentage),
而且我会 运行 并行多次执行该函数。
我想要实现的效果如下,f(10000000), f(15000000), f(7000000):
For x = 10000000, 43% completed
For x = 15000000, 31% completed
For x = 7000000, 77% completed
并且百分比将在各自的行中更新而不替换 x 的其他值,在此函数 f
中将同时 运行ning 三次。
我尝试使用回车 return '\r' 但这会替换每一行并且只会造成混乱。
感谢您抽出宝贵时间阅读本文post!希望你能告诉我。
我正在使用 Python 2.7,但如果它只能通过 Python 3 实现,我愿意接受建议。
诅咒
正如@Keozon 在评论中提到的,实现这一目标的一种方法是使用 curses 库。
python 网站上有一个 good guide for curses。
ANSI 转义码
或者,您可以尝试使用 ANSI escape codes 来移动光标。
这在 Python3 中,但它在任何版本中都可以正常工作,您只需要更改周围的打印语句(或 from __future__ import print_function
)。
print('Hello')
print('World')
print('3[F3[F3[K', end='') # Up, Up, Clear line
# Cursor is at the 'H' of 'Hello'
print('Hi') # Overwriting 'Hello'
# Cursor is at the 'W' of 'World'
print('3[E', end='') # Down
# Cursor is on the blank line after 'World'
print('Back to the end')
输出:
Hi
World
Back to the end
编辑:
我在这里为你做了太多的工作,但是嘿,这里基本上是一个使用我上面提到的 ANSI 方法的完整解决方案:
import time
import random
class ProgressBar:
def __init__(self, name):
self._name = name
self._progress = 0
@property
def name(self):
return self._name
def get_progress(self):
"""
Randomly increment the progress bar and ensure it doesn't go
over 100
"""
self._progress += int(random.random()*5)
if self._progress > 100:
self._progress = 100
return self._progress
class MultipleProgressBars:
def __init__(self, progress_bars):
self._progress_bars = progress_bars
self._first_update = True
self._all_finished = False
@property
def all_finished(self):
"""
A boolean indicating if all progress bars are at 100
"""
return self._all_finished
def update(self):
"""
Update each progress bar
"""
# We don't want to move up and clear a line on the first run
# so we have a flag to make sure this only happens on later
# calls
if not self._first_update:
# Move up and clear the line the correct number of times
print('3[F3[K'*len(self._progress_bars),end='', sep='')
num_complete = 0 # Number of progress bars complete
for progress_bar in self._progress_bars:
name = progress_bar.name
progress = progress_bar.get_progress()
if progress == 100:
num_complete += 1
# Print out a progress bar (scaled to 40 chars wide)
print(
name.ljust(10),
'[' + ('='*int(progress*0.4)).ljust(40) + ']',
str(progress)+'%')
if num_complete == len(self._progress_bars):
self._all_finished = True
self._first_update = False # Mark the first update done
# Create a list of ProgressBars and give them relevant names
progress_bars = [
ProgressBar('James'),
ProgressBar('Bert'),
ProgressBar('Alfred'),
ProgressBar('Frank')
]
# Create a new instance of our MultipleProgressBars class
mpb = MultipleProgressBars(progress_bars)
# Keep updating them while at least one of them is still active
while not mpb.all_finished:
mpb.update()
time.sleep(0.2)