我正在try 使用在Docker容器中运行的应用程序中的Python来处理tar文件.因为我不经常使用tarfile,所以我起草了一些代码并在我本地的Python环境中运行它,这样在我在容器中运行它之前,我可以验证它是否以我想要的方式工作.

为简单起见,假设我有一个包含文件test_file.py的目录a/,并且我递归地将a/压缩为tar文件file.tar.gz.当我判断tar文件的内容时,我看到了目录和文本文件(a/a/test_file.py).当我在本地环境中解压缩该目录时,我获得了该目录及其内容.当我在容器中运行相同的代码时,我只得到没有文件的空目录.遇到这个问题后,我做了一些搜索,找到了像Extract only a single directory from tar (in python)这样的帖子,它们明确建议包括您想要解压缩的所有文件,而不是假设它们会随父目录一起提供,所以我可以这样做.但是...

让我烦恼的是我的两个环境之间的这种不一致的行为!我的本地环境在Ubuntu 22.04上使用的是Python3.9.15.我的Docker容器在Ubuntu 18.04上使用的是Python3.10.9.因此,环境是不同的,但仍然存在这种差异似乎很奇怪.

以下是一些示例代码.我知道我之前提到过使用extract的方法.我首先try 使用它,然后使用members kwarg切换到extractall,我得到了相同的行为--文件也在我的本地环境中存在,但不在Docker容器中.

import logging
import os
from pathlib import Path
import tarfile
import tempfile


def main():
    with tempfile.TemporaryDirectory() as temp_dir:
        # make a tar file with one directory that contains one file
        file_path = Path(temp_dir) / "file.tar.gz"
        os.chdir(temp_dir)
        logging.info("Changed dir to %s", os.getcwd())
        subdir = "a"
        os.mkdir(subdir)
        with open(Path(subdir) / "test_file.py", "w") as file_obj:
            file_obj.write("import this\n")
        with tarfile.open(file_path, "w:gz") as tar:
            tar.add(subdir, recursive=True)

        # unpack tar file
        with tarfile.open(file_path) as tar:
            file_names = tar.getnames()
            logging.info(file_names)
            members = [tar.getmember(subdir)]
            tar.extractall(path=temp_dir, members=members)

        # check contents of extracted directory
        dir_path = Path(temp_dir) / subdir
        output = os.listdir(dir_path)
        logging.info("%s contents: %s", dir_path, output)

日志(log)记录显示,在两个环境中,目录和文件都在tar文件中(从call到tar.getnames()),但最后listdir调用的输出在一个环境中是文件,在另一个环境中是一个空列表.

推荐答案

有两个问题.我假设您在环境中只得到了一个空的子目录,您只运行了解压缩部分.

  1. 您从不删除原始文件,而是将其解压缩到同一目录中.因此,当您解压缩时,无法区分您在磁盘上看到的文件是解压缩的结果,还是原始文件.在创建tarball之后投入shutil.rmtree(subdir)应该可以解决这个问题.

  2. 一旦您解决了第一个问题,您将看到结果只是创建了空目录.这是因为您显式地请求了它:您的members只是["a"](或者更确切地说,它的TarInfo版本),因此只提取了["a"],就像您的链接警告您的那样.go 掉members=members参数或使用members = [tar.getmember("a"), tar.getmember("a/test_file.py")]可以得到想要的结果.即使是[tar.getmember("a/test_file.py")]也可以:在本例中,将为您创建一个目录,即使它没有列出用于解压缩.)

Python相关问答推荐

使用Python从HTTP打印值

Flask:如何在完整路由代码执行之前返回验证

合并同名列,但一列为空,另一列包含值

具有多个组的条形图的不同y标度

过载功能是否包含Support Int而不是Support Int?

如何在Deliveryter笔记本中从同步上下文正确地安排和等待Delivercio代码中的结果?

acme错误-Veritas错误:模块收件箱没有属性linear_util'

需要计算60,000个坐标之间的距离

将pandas Dataframe转换为3D numpy矩阵

修复mypy错误-赋值中的类型不兼容(表达式具有类型xxx,变量具有类型yyy)

为什么NumPy的向量化计算在将向量存储为类属性时较慢?'

在Python中,从给定范围内的数组中提取索引组列表的更有效方法

mypy无法推断类型参数.List和Iterable的区别

Python导入某些库时非法指令(核心转储)(beautifulsoup4."" yfinance)

不能使用Gekko方程'

Polars将相同的自定义函数应用于组中的多个列,

如何使用使用来自其他列的值的公式更新一个rabrame列?

为什么调用函数的值和次数不同,递归在代码中是如何工作的?

当单元测试失败时,是否有一个惯例会抛出许多类似的错误消息?

30个非DATETIME天内的累计金额