你也可以手敲一个高速下载器(七)加一点点细节

169 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情


你也可以手敲一个高速下载器(七)加一点点细节

前言

我们之前的程序对文件的处理比较简陋,直接保存的文件路径没有做文件夹判空处理,而且打印的出来的信息不够详细,并且日志里面的内容是不适合直接展现给用户的,所以我们这一节给我们的程序加一点点细节

保存目录

在我们之前测试时,只是传递了一个文件名放在了当前目录下,只是为了方便而已。但在真实场景下会传递真实的目录和文件名的,所以我们要做一定的处理。

pathlib库

在以前大家操作目录和文件时,会第一时间想起os.path库来使用,但自python3.4开始,官方新推出了一个新库:pathlib --- 面向对象的文件系统路径,这个库操作起来更加方便,这里不多做介绍,大家自己去看文档:

官方文档:docs.python.org/zh-cn/3/lib…

路径参数修改

在上一节中,初始化传递的路径为save_path,意思为保存的路径,但在这里我们把它分开,分为文件夹参数和文件名参数,然后文件夹的默认参数是当前可执行文件同一目录下的downloads文件夹,默认文件名为url参数中的文件名,示例代码如下:

    def __init__(
            self,
            url: str,
            save_path: str = None,
            save_name: str = None,
            concurrency: int = 64
    ):
        """
        :param url: 要下载的地址
        :param save_path: 保存的文件路径
        :param save_path: 保存的文件名字
        :param concurrency: 并发的数量
        """
        self.url = url
        # 默认下载路径为当前目录下单downloads文件夹
        self.save_path = Path(save_path or 'downloads').absolute()
        # 文件名默认从url中获取
        self.save_name = save_name or Path(url).name
        # 路径不存在则创建
        if not self.save_path.exists():
            self.save_path.mkdir(parents=True)

其中absolute()方法的意思的获取绝对路径,其实使用者相对的路径是完全没问题的,但打印日志上面使用绝对路径更加友好一点。

日志保存

日志方面我们之前也是直接保存在当前目录下面的,并且是以下载文件的路径加.log为名字的,这里我们做一些修改。我们把日志保存在当前可执行路径下的logs文件夹的当前日期+.log文件里面,这样做的好处是日志保存的一个文件夹后续查询方便,而且是对用户不直接可见的,不用手动去删除单个文件,只需定期清理日志文件夹即可,下面是相关代码:

    # 设置日志文件夹,不存在则创建
    self.log_path = Path("logs") / f"{datetime.now().date().isoformat()}.log"
    if not self.log_path.parent.exists():
        self.log_path.parent.mkdir(parents=True)

    # 初始化日志
    logger.remove()
    logger.add(self.log_path, level="DEBUG")

可以看出来,我们在初始化日志的时候,也发生了修改,我们去掉了控制台输出的日志,直接把所以的日志保存在了文件中。

使用rich.console代替控制台日志

在前面我们是把基本的信息以loger.info的形式显示出来的,现在则修改为使用rich.console的形式显示基本信息,然后把开始下载时打印的信息更详细的保存在日志中,同时使用rich.table的形式显示出来,以下是示例代码:

  def print_download_info(self):
      """
      打印下载信息
      :return:
      """
      headers = ["资源名字", "资源路径", "日志文件路径", "是否允许断点续传", "资源总大小"]
      datas = [
          self.save_name,
          str(self.save_path / self.save_name),
          str(self.log_path.absolute()),
          '是' if self.accept_ranges else '否',
          self.file_size
      ]
      table = Table(*headers, show_header=True, header_style="bold magenta")
      table.add_row(*datas)
      self.console.print(table)

上面的代码应该很易懂的,就是一个表头列表和一个表数据的礼包,最后使用rich.Table类包装,在显示出来就好了,下面是示例图片:

代码仓库:

本节的代码以上传至 Github,请自行下载及观看:第七节代码

结语

这篇主要是完善了程序的一些细节上和使用的体验,当然程序还有很多不足的地方,我们逐步完善,敬请期待!!!