Python 3: 在不写入磁盘的情况下提取 tar.gz 存档

Python 3: Extract tar.gz archive without writing to disk

如标​​题所说,有没有办法在不将文件写入磁盘的情况下提取 tar.gz 存档(存档是从互联网上下载的)。在 bash 或任何其他 shell 中,我可以将 curl 或 wget 的输出通过管道传输到 tar:

curl -L "https://somewebsite.com/file.tar.gz" | tar xzf -

我也可以在 python 中做这样的事情吗?

编辑:我正在使用 urllib 下载数据。我目前正在做这样的事情来下载和写入文件:

from urllib.request import urlopen

filename = "/home/bob/file.tar.gz"
url      = "https://website.com/file.tar.gz"

file = open(filename, "wb")
file.write(urlopen(url).read())
file.close

无需将 TAR 文件写入磁盘,您可以使用 python subprocess 模块为您执行 运行 shell 命令:

import subprocess

# some params
shell_cmd = 'curl -L "https://somewebsite.com/file.tar.gz" | tar xzf -'
i_trust_this_string_cmd = True
throw_error_on_fail = True
timeout_after_seconds = 10 # or None
convert_output_from_bytes_to_string = True
#

# run shell as subprocesses to this one and get results
cp = subprocess.run(
    [shell_cmd],
    shell=i_trust_this_string_cmd,
    check=throw_error_on_fail,
    timeout=timeout_after_seconds,
    text=convert_output_from_bytes_to_string
)

#status_code = cp.returncode

try:
    cp.check_returncode() # triggers exceptions if errors occurred
    print(cp.stdout) # if you want to see the output (text in this case)
except subprocess.CalledProcessError as cpe:
    print(cpe)
except subprocess.TimeoutExpired as te:
    print(te)

如果您想要更多控制,可以为 STDOUT、STDERR 提供一个 PIPE,例如

with open('/tmp/stdout.txt', 'w+') as stdout:
    with open('/tmp/stderr.txt', 'w+') as stderr:
        cp = subprocess.run([...], stdout=stdout, stderr=stderr)
        ...

在 kenny 评论的帮助下,我通过解析从 urlopen 获得的数据、使用 BytesIO 并将其用作 tarfile.open:

的 fileobj 参数来完成我想做的事情
from urllib.request import urlopen
import tarfile
from io import BytesIO

r = urlopen("https://url/file.tar.gz")
t = tarfile.open(name=None, fileobj=BytesIO(r.read()))
t.extractall("/somedirectory/")
t.close()