如何仅用Python从GitHub仓库下载单个文件
用纯Python实现从GitHub仓库下载单个文件
你可以通过Python标准库的urllib.request和tarfile模块实现需求,无需调用任何bash命令,核心思路是下载仓库压缩包到内存,再从中提取目标文件:
标准库实现(无额外依赖)
import urllib.request import tarfile from io import BytesIO from urllib.error import URLError, HTTPError # 目标仓库的master分支压缩包URL tar_url = "https://github.com/mikolalysenko/lena/archive/master.tar.gz" # 要提取的文件名 target_file_name = "lena.png" try: # 下载压缩包到内存缓冲区 with urllib.request.urlopen(tar_url) as response: tar_buffer = BytesIO(response.read()) # 读取内存中的压缩包 with tarfile.open(fileobj=tar_buffer, mode='r:gz') as tar: # 筛选目标文件(压缩包内路径格式为「仓库名-分支名/文件名」) target_members = [member for member in tar.getmembers() if member.name.endswith(target_file_name)] if not target_members: raise FileNotFoundError(f"目标文件 {target_file_name} 未在压缩包中找到") # 修改文件存储路径,去掉前缀目录,直接存到当前工作目录 target_member = target_members[0] target_member.name = target_file_name # 提取文件 tar.extract(target_member) print(f"文件 {target_file_name} 已成功保存到当前目录") except HTTPError as e: print(f"请求失败:HTTP {e.code} - {e.reason}") except URLError as e: print(f"网络错误:{e.reason}") except tarfile.TarError as e: print(f"压缩包解析错误:{e}") except FileNotFoundError as e: print(e)
基于requests库的简洁实现
如果允许安装第三方库,requests能让代码更简洁:
- 先安装依赖:
pip install requests
- 实现代码:
import requests import tarfile from io import BytesIO tar_url = "https://github.com/mikolalysenko/lena/archive/master.tar.gz" target_file_name = "lena.png" try: response = requests.get(tar_url) response.raise_for_status() # 检查请求是否成功 with tarfile.open(fileobj=BytesIO(response.content), mode='r:gz') as tar: target_member = next(m for m in tar.getmembers() if m.name.endswith(target_file_name)) target_member.name = target_file_name tar.extract(target_member) print(f"文件 {target_file_name} 已成功保存到当前目录") except requests.exceptions.RequestException as e: print(f"请求错误:{e}") except tarfile.TarError as e: print(f"压缩包解析错误:{e}") except StopIteration: print(f"目标文件 {target_file_name} 未在压缩包中找到")
核心逻辑说明
- 下载分支压缩包:GitHub仓库分支压缩包的URL格式为
https://github.com/<用户名>/<仓库名>/archive/<分支名>.tar.gz - 内存处理压缩包:用
BytesIO将下载的二进制数据转为文件对象,避免写入临时文件 - 提取目标文件:遍历压缩包内的文件成员,筛选出目标文件后修改其
name属性去掉前缀目录,确保文件直接保存到当前工作目录
内容的提问来源于stack exchange,提问作者Johannes Wiesner
相关产品推荐
相关产品推荐

