本答案提供了一个基于rich
进度条的工作示例,每个克隆过程的步骤都有一个进度条和一个新任务被分派。这个答案与我的另一个答案非常相似,但我认为将它们放在两个不同的帖子中可以提高可读性。主要区别在于,由于rich允许在一个进度条上下文中有多个任务,因此只需要进入和退出一次上下文-而不是每个阶段都需要。
from __future__ import annotations
import git
from rich import console, progress
class GitRemoteProgress(git.RemoteProgress):
OP_CODES = [
"BEGIN",
"CHECKING_OUT",
"COMPRESSING",
"COUNTING",
"END",
"FINDING_SOURCES",
"RECEIVING",
"RESOLVING",
"WRITING",
]
OP_CODE_MAP = {
getattr(git.RemoteProgress, _op_code): _op_code for _op_code in OP_CODES
}
def __init__(self) -> None:
super().__init__()
self.progressbar = progress.Progress(
progress.SpinnerColumn(),
progress.TextColumn("[progress.description]{task.description}"),
progress.BarColumn(),
progress.TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
"eta",
progress.TimeRemainingColumn(),
progress.TextColumn("{task.fields[message]}"),
console=console.Console(),
transient=False,
)
self.progressbar.start()
self.active_task = None
def __del__(self) -> None:
self.progressbar.stop()
@classmethod
def get_curr_op(cls, op_code: int) -> str:
"""Get OP name from OP code."""
op_code_masked = op_code & cls.OP_MASK
return cls.OP_CODE_MAP.get(op_code_masked, "?").title()
def update(
self,
op_code: int,
cur_count: str | float,
max_count: str | float | None = None,
message: str | None = "",
) -> None:
if op_code & self.BEGIN:
self.curr_op = self.get_curr_op(op_code)
self.active_task = self.progressbar.add_task(
description=self.curr_op,
total=max_count,
message=message,
)
self.progressbar.update(
task_id=self.active_task,
completed=cur_count,
message=message,
)
if op_code & self.END:
self.progressbar.update(
task_id=self.active_task,
message=f"[bright_black]{message}",
)
使用它 - 完全克隆:
project_url = "https://github.com/u-boot/u-boot"
print("Cloning Git Repository 'u-boot' ('master' branch)...")
git.Repo.clone_from(
url=project_url,
to_path="u-boot",
progress=GitRemoteProgress(),
)
print("Done.")
![Progress bar in action - full clone](https://istack.dev59.com/TUvRK.gif)
使用浅克隆:
project_url = "https://github.com/u-boot/u-boot"
print("Cloning Git Repository 'u-boot' ('master' branch)...")
git.Repo.clone_from(
url=project_url,
to_path="u-boot",
depth=1,
progress=GitRemoteProgress(),
)
print("Done.")
![Progress bar in action - shallow clone](https://istack.dev59.com/T602m.gif)
PS: 由于其较大的大小和可跟踪的克隆进度,使用u-boot
仓库
TypeError: 不支持的操作数类型:'float' 和 'str'
- Andrea Ricchi