从子进程的标准输出的 tar 中读取单个文件

Fla*_*ius 2 python

如何从命令的标准输出读取单个文件的内容而不访问磁盘?

我想出了这样的东西:

def get_files_from(sha, files):
    from subprocess import Popen, PIPE
    import tarfile
    p = Popen(["git", "archive", sha], bufsize=10240, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    tar = tarfile.open(fileobj=p.stdout, mode='r|')
    p.communicate()
    members = tar.getmembers()
    names = tar.getnames()
    contents = {}
    for fname in files:
        if fname not in names:
            contents[fname] = None
            continue
        else:
            idx = names.index(fname)
            contents[fname] = members[idx].tobuf()
            contents[fname] = tar.extractfile(members[idx]) #<--- HERE

    tar.close()
    return contents
Run Code Online (Sandbox Code Playgroud)

问题是.read()在标记的线路上添加呼叫

            contents[fname] = tar.extractfile(members[idx]) #<--- HERE
Run Code Online (Sandbox Code Playgroud)

会给出错误:

tarfile.StreamError:不允许向后查找

那么如何获取文件的内容呢?

Mar*_*ers 5

您拼写错误了mode=参数,而是写了more=

tar = tarfile.open(fileobj=p.stdout, mode='r|')
Run Code Online (Sandbox Code Playgroud)

.tell()如果您正确指定模式,则不会被调用。:-)

然后,您必须循环tarfile 对象以提取成员,您无法从 tarfile 中读取任意文件:

for entry in tar:
    # test if this is a file you want.
    if entry.name in files:
        f = tar.extractfile(entry) 
Run Code Online (Sandbox Code Playgroud)

您不能使用任何.getnames(),.getmember().getmembers()方法,因为这些方法需要对文件进行完整扫描,将文件指针放在末尾,并使您无法读取条目数据本身。