如何使用Python3.6 tarfile模块从内存读取并下载URL中的tar文件解压?
解决从URL下载xz压缩Tar包并提取到本地的问题
我来帮你搞定这个问题!你遇到的两个错误其实都是有明确原因的,咱们一步步拆解解决:
先分析你遇到的错误
第一个错误:TypeError: expected str, bytes or os.PathLike object, not _io.BytesIO
你一开始直接把BytesIO对象传给了TarFile的第一个参数,而TarFile的第一个参数默认是文件路径字符串,要传入内存中的字节流,必须用fileobj关键字参数来指定——你后来的修改方向是对的,但还没解决核心问题。
第二个错误:tarfile.InvalidHeaderError: invalid header
这个问题的关键是:你下载的文件是tar.xz格式(xz压缩的tar包),而TarFile默认的mode='r'只会处理未压缩的tar文件,它无法自动识别xz压缩格式,所以才会报“无效头”的错误。
修正后的完整代码
我们只需要在创建TarFile时指定mode='r:xz',告诉它要处理xz压缩的tar包,同时正确传入fileobj参数即可:
#!/usr/bin/python3.6 # -*- coding: utf-8 -*- from pathlib import Path from io import BytesIO from urllib.request import Request, urlopen from urllib.error import URLError from tarfile import TarFile def get_url_response(url): req = Request(url) try: response = urlopen(req) except URLError as e: if hasattr(e, 'reason'): print('We failed to reach a server.') print('Reason: ', e.reason) elif hasattr(e, 'code'): print('The server couldn\'t fulfill the request.') print('Error code: ', e.code) return None # 出错时返回None,避免后续调用read()报错 else: # everything is fine return response url = 'https://dl.opendesktop.org/api/files/download/id/1566630595/s/6cf6f74c4016e9b83f062dbb89092a0dfee862472300cebd0125c7a99463b78f4b912b3aaeb23adde33ea796ca9232decdde45bb65a8605bfd8abd05eaee37af/t/1567158438/c/6cf6f74c4016e9b83f062dbb89092a0dfee862472300cebd0125c7a99463b78f4b912b3aaeb23adde33ea796ca9232decdde45bb65a8605bfd8abd05eaee37af/lt/download/Blue-Maia.tar.xz' dst = Path().cwd() / 'Tar' response = get_url_response(url) if response: # 先判断响应是否有效 # 指定mode='r:xz'处理xz压缩的tar包,同时传入内存字节流对象 with TarFile.open(fileobj=BytesIO(response.read()), mode='r:xz') as tfile: tfile.extractall(path=dst) print(f"文件已成功提取到:{dst}")
补充说明
mode='r:xz'是核心:它告诉TarFile读取xz压缩的tar归档文件,同理如果是gz压缩的tar包,就用mode='r:gz'。- 我给
get_url_response函数加了return None的逻辑,避免出错时response为None导致后续调用response.read()报错。 extractall会自动创建不存在的目标文件夹,所以不用额外手动创建dst路径。
内容的提问来源于stack exchange,提问作者Sun Bear
相关产品推荐
相关产品推荐

