2

ディスクにアクセスせずに、コマンドの stdout から個々のファイルの内容を読み取るにはどうすればよいですか?

私はこのようなものを思いついた:

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

.read()問題は、マークされた回線にコールを追加することです

            contents[fname] = tar.extractfile(members[idx]) #<--- HERE

エラーが発生します:

tarfile.StreamError: 逆方向へのシークは許可されていません

では、ファイルの内容を取得するにはどうすればよいでしょうか。

4

2 に答える 2

4

パラメータのつづりを間違えました。代わりに次のようにmode=書きました。more=

tar = tarfile.open(fileobj=p.stdout, mode='r|')

.tell()モードを正しく指定すると呼び出されません。:-)

次に、tarfile オブジェクトをループしてメンバーを抽出する必要があります。tarfile から任意のファイルを読み取ることはできません。

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

.getnames().getmember()またはメソッドのいずれも使用できません。.getmembers()これらのメソッドはファイルのフル スキャンを必要とし、ファイル ポインタを最後に置き、エントリ データ自体を読み取る手段がないままにするためです。

于 2012-12-02T09:08:54.840 に答える
0

興味のある方へ:

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()
    contents = {}
    doall = files == '*'
    if not doall:
        files = set(files)
    for entry in tar:
        if (isinstance(files, set) and entry.name in files) or doall:
            tf = tar.extractfile(entry)
            contents[entry.name] = tf.read()
            if not doall:
                files.discard(entry.name)

    if not doall:
        for fname in files:
            contents[fname] = None

    tar.close()
    return contents

print get_files_from("a8c11fcee68881dfb86095aa36290fb304047cf1", ['README.MD', 'foo'])
print get_files_from("a8c11fcee68881dfb86095aa36290fb304047cf1", '*')

パッチ歓迎!

于 2012-12-02T10:39:33.643 に答える