You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中TarFile.extractall自动添加子目录的路径问题求助

tar包提取自动生成额外目录的原因与解决方法

问题描述

我编写了一段下载并提取数据集的代码,问题出在extractall()这一行:

housing_tarball.extractall(path='datasets') 
  • 设置path='dataset'时,文件被提取到/dataset/housing目录;
  • 设置path='dataset/housing/'时,文件被提取到/dataset/housing/housing目录;
    代码会自动添加housing目录,但我并未在path中指定,想知道这是否与tar包的存储路径tarball_path = Path("datasets/housing/housing.tgz")有关?

完整代码

from pathlib import Path
import pandas as pd
import tarfile
import urllib.request
import os

def load_housing_data():
    tarball_path = Path("datasets/housing/housing.tgz")

    if not tarball_path.is_file():
        Path("datasets/housing").mkdir(parents=True, exist_ok=True) # 创建目录(如果不存在)
        url = "https://github.com/ageron/data/raw/main/housing.tgz"

        with urllib.request.urlopen(url) as response, tarball_path.open(mode="wb") as tarball_file: # 以二进制写入模式打开文件
            tarball_file.write(response.read()) # 将响应内容写入文件

    with tarfile.open(tarball_path) as housing_tarball: # 打开tar包
        housing_tarball.extractall(path='datasets') # 将所有文件提取到datasets目录

    # 删除tar包文件
    os.remove(tarball_path)

    return pd.read_csv("datasets/housing/housing.csv")

解答

这个问题和tar包的存储路径完全无关,核心原因是你下载的housing.tgz压缩包内部本身就包含一个housing目录,housing.csv文件就放在这个目录里。tarfile.extractall()的默认行为是完全还原压缩包内的目录结构,所以不管你指定什么path,都会把压缩包里的housing目录连同里面的文件一起解压到目标路径下。

解决方法

有两种常用的处理方式:

方法1:解压后调整文件路径

解压完成后,把目标文件移动到你想要的位置,再删除多余的目录:

import shutil

# 解压后执行以下代码
shutil.move("datasets/housing/housing.csv", "datasets/housing.csv")
shutil.rmtree("datasets/housing")  # 删除空的子目录
方法2:直接提取单个文件并修改路径(更高效)

如果只需要housing.csv,可以跳过解压整个包,直接提取目标文件并修改它的存储路径,去掉外层的housing目录:

with tarfile.open(tarball_path) as housing_tarball:
    # 获取压缩包内的csv文件成员
    csv_member = housing_tarball.getmember("housing/housing.csv")
    # 修改成员的名称,去掉外层的housing目录
    csv_member.name = "housing.csv"
    # 提取到指定目录
    housing_tarball.extract(csv_member, path='datasets')

修改后的完整代码

用方法2优化后的代码如下:

from pathlib import Path
import pandas as pd
import tarfile
import urllib.request
import os

def load_housing_data():
    tarball_path = Path("datasets/housing/housing.tgz")

    if not tarball_path.is_file():
        Path("datasets/housing").mkdir(parents=True, exist_ok=True)
        url = "https://github.com/ageron/data/raw/main/housing.tgz"

        with urllib.request.urlopen(url) as response, tarball_path.open(mode="wb") as tarball_file:
            tarball_file.write(response.read())

    with tarfile.open(tarball_path) as housing_tarball:
        # 直接提取csv文件并调整路径
        csv_member = housing_tarball.getmember("housing/housing.csv")
        csv_member.name = "housing.csv"
        housing_tarball.extract(csv_member, path='datasets')

    os.remove(tarball_path)
    # 删除临时创建的空目录
    try:
        os.rmdir(Path("datasets/housing"))
    except OSError:
        pass

    return pd.read_csv("datasets/housing.csv")

内容的提问来源于stack exchange,提问作者user16497397

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:45:33