0

関数を考えると

def get_files_from_sha(sha, files):
    from subprocess import Popen, PIPE
    import tarfile
    if 0 == len(files):
        return {}
    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

これは のいくつかの値のループで呼び出され、shaしばらくすると (私の場合は 4 回の反復)、 への呼び出しで失敗し始め、次tf.read()のメッセージが表示されます。

Traceback (most recent call last):
  File "../yap-analysis/extract.py", line 243, in <module>
    commits, identities, identities_by_name, identities_by_email, identities_freq = build_commits(commits)
  File "../yap-analysis/extract.py", line 186, in build_commits
    commit = get_commit(commit)
  File "../yap-analysis/extract.py", line 84, in get_commit
    contents = get_files_from_sha(commit['sha'], files)
  File "../yap-analysis/extract.py", line 42, in get_files_from_sha
    contents[entry.name] = tf.read()
  File "/usr/lib/python2.7/tarfile.py", line 817, in read
    buf += self.fileobj.read()
  File "/usr/lib/python2.7/tarfile.py", line 737, in read
    return self.readnormal(size)
  File "/usr/lib/python2.7/tarfile.py", line 746, in readnormal
    return self.fileobj.read(size)
  File "/usr/lib/python2.7/tarfile.py", line 573, in read
    buf = self._read(size)
  File "/usr/lib/python2.7/tarfile.py", line 581, in _read
    return self.__read(size)
  File "/usr/lib/python2.7/tarfile.py", line 606, in __read
    buf = self.fileobj.read(self.bufsize)


ValueError: I/O operation on closed file

サブプロセスが作成しようとするいくつかの並列化があると思われます (?)。

実際の原因と、それをpython2でクリーンかつ堅牢な方法で解決する方法は何ですか?

4

2 に答える 2

1

あなたの問題はp.communicate(). このメソッドは stdin に送信し、stdout と stderr (キャプチャしていないもの) から読み取り、プロセスが終了するのを待ちます。

tarfileプロセスの stdout から読み取ろうとしていますが、その時点でプロセスが終了しているため、エラーが発生します。

私はあなたのコードを実行しようとはしていません (私は にアクセスできませんgit) p.communicate

于 2012-12-02T11:56:24.843 に答える
1

インスタンスでは使用.communicate()しないでください。完了するまでストリームPopenを読み取ります。stdoutドキュメントから:

プロセスとの対話: stdin にデータを送信します。ファイルの終わりに達するまで、stdout および stderr からデータを読み取ります。

evenのコードは、パイプの明示的な呼び出しを.communicate()追加します。.close()stdout

への呼び出しを削除するだけで十分ですが、tarfile の内容を読み取った.communicate()に a も追加してください。.wait()

tar.close()
p.stdout.close()
p.wait()

それtar.close()も閉じる可能性がありますが、そこp.stdoutに余分なものがあっても.close()問題ありません。

于 2012-12-02T11:56:49.540 に答える