3

tar.gzファイルから1つのファイルだけを読み取ろうとしています。tarfileオブジェクトに対するすべての操作は正常に機能しますが、具象メンバーから読み取ると、常にStreamErrorが発生します。次のコードを確認してください。

import tarfile
fd = tarfile.open('file.tar.gz', 'r|gz')
for member in fd.getmembers():
    if not member.isfile():
        continue
    cfile = fd.extractfile(member)
    print cfile.read()
    cfile.close()
fd.close()

cfile.read()は常に「tarfile.StreamError:後方シークは許可されていません」を引き起こします

ファイルにダンプするのではなく、コンテンツをmemに読み取る必要があります(extractallは正常に機能します)

ありがとうございました!

4

2 に答える 2

10

問題はこの行です:

fd = tarfile.open('file.tar.gz', 'r|gz')

あなたは欲しくない'r|gz'、あなたは欲しがって'r:gz'いる。

些細なtarballでコードを実行すると、を印刷してmember表示することもできます。test/fooそうすると、同じエラーが発生しreadます。

使用するように修正すれば'r:gz'動作します。

ドキュメントから:

modeは、「filemode [:compression]」の形式の文字列である必要があります

..。

特別な目的のために、モードの2番目の形式があります:'filemode|[compression]'。tarfile.open()は、データをブロックのストリームとして処理するTarFileオブジェクトを返します。ファイルに対してランダムなシークは実行されません…このバリアントは、たとえばsys.stdin、ソケットファイルオブジェクト、またはテープデバイスと組み合わせて使用​​します。ただし、このようなTarFileオブジェクトは、ランダムにアクセスできないという制限があります。例を参照してください。

'r|gz'シークできないストリームがある場合を対象としており、操作のサブセットのみを提供します。残念ながら、許可されている操作を正確に文書化していないようです。また、どの例もこの機能を使用していないため、例へのリンクは役に立ちません。したがって、ソースを読むか、試行錯誤してそれを理解する必要があります。

ただし、通常のシーク可能なファイルがあるので、それについて心配する必要はありません。を使用するだけ'r:gz'です。

于 2013-02-08T10:36:22.887 に答える
0

ファイルモードに加えてseek、ネットワークストリームを試してみました。

ファイルを作成しようとしたときに同じエラーが発生したrequests.getため、すべてをtmpディレクトリに抽出しました。

# stream == requests.get
inputs = [tarfile.open(fileobj=LZMAFile(stream), mode='r|')]
t = "/tmp"
for tarfileobj in inputs:        
    tarfileobj.extractall(path=t, members=None)
for fn in os.listdir(t):
    with open(os.path.join(t, fn)) as payload:
        print(payload.read())
于 2016-12-17T02:48:13.807 に答える