如何配置tqdm进度条,将迭代耗时单位从秒改为分钟?
Got it, I totally get why you’d want this—when your iterations take minutes or hours, seeing 21m/it is way easier to parse than 1283.31s/it. Let’s walk through the best ways to make this happen, starting with the integrated approach you prefer.
Preferred Integrated Method: Custom Bar Formatting
tqdm lets you fully customize its display with the bar_format parameter. You can either force all times to show in minutes, or dynamically switch between seconds, minutes, and hours based on how long each iteration takes (the smarter option).
Dynamic Unit Switching (Recommended)
This automatically picks the most intuitive unit for your iteration time:
from tqdm import tqdm import time def format_per_iter_time(seconds): if seconds < 60: return f"{seconds:.1f}s/it" elif seconds < 3600: return f"{seconds/60:.1f}m/it" else: return f"{seconds/3600:.1f}h/it" # Use a lambda in bar_format to inject our formatted time for item in tqdm(range(5), bar_format=lambda stats: ( "{l_bar}{bar}| {n_fmt}/{total_fmt} " "[{elapsed}<{remaining}, {time_per_iter}]" ).format(time_per_iter=format_per_iter_time(stats['rate_inv']), **stats)): time.sleep(120) # Simulate a 2-minute iteration
Here’s what’s happening:
- We define a helper function
format_per_iter_timethat converts raw seconds to the right unit. - The lambda passed to
bar_formatgets a dictionary of tqdm’s internal metrics (likerate_inv, which is average seconds per iteration). We use this to generate our formatted time string and plug it into the bar layout.
If you run this, you’ll see 2.0m/it instead of 120.0s/it. For shorter iterations (e.g., 30 seconds), it’ll show 30.0s/it, and for multi-hour runs, X.Xh/it.
Force All Display to Minutes
If you want every iteration time to show in minutes regardless of length, simplify the format string:
from tqdm import tqdm import time for i in tqdm(range(10), bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_inv / 60:.1f}m/it]"): time.sleep(7) # Simulate a 7-second iteration (shows as 0.1m/it)
This directly divides the rate_inv (seconds) value by 60 to get minutes, then formats it into the bar.
Alternative Workaround: Using postfix
If you’d rather not overhaul the main bar format, you can calculate and display the formatted time in the postfix section (the extra info at the end of the bar):
from tqdm import tqdm import time total_iterations = 5 start_time = time.time() with tqdm(total=total_iterations) as pbar: for i in range(total_iterations): time.sleep(90) # Simulate 1.5-minute iteration pbar.update(1) # Calculate average time per iteration so far avg_time = (time.time() - start_time) / (i + 1) # Format the time string if avg_time < 60: time_str = f"{avg_time:.1f}s/it" elif avg_time < 3600: time_str = f"{avg_time/60:.1f}m/it" else: time_str = f"{avg_time/3600:.1f}h/it" pbar.set_postfix({"Avg Time": time_str})
This adds a label like Avg Time: 1.5m/it to the end of the progress bar. It’s a bit more manual, but useful if you want to keep the default time display alongside your formatted version.
Wrap-Up
The custom bar_format approach is the most integrated solution—it replaces the default Xs/it display directly, which is exactly what you asked for. The dynamic unit switching version is especially handy because it adapts to whatever iteration length you’re dealing with.
内容的提问来源于stack exchange,提问作者pedjjj

