2012-12-02 67 views
2

如何從命令的stdout中讀取單個文件的內容而不敲擊磁盤?從子進程的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: seeking backwards is not allowed

那麼如何獲取文件的內容呢?

回答

3

你拼寫錯誤mode=參數,你寫more=代替:

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

.tell()如果你正確指定的模式將不會被調用。 :-)

然後您就必須遍歷的tar文件對象提取會員,你不能從tar文件讀取任意文件:

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

不能使用任何.getnames()的,.getmember().getmembers()方法,因爲這些方法需要對文件進行全面掃描,將文件指針放在最後,並且讓您無法讀取條目數據本身。

+0

謝謝,這有助於我進一步。然而...請看我的更新,它不起作用... – Flavius

+1

@Flavius:請注意改變你的問題來解決你遇到的每個新問題並不是一個好習慣。例如,我解決了你最初的問題。很難爲改變問題的答案投票。 –

+0

我應該用相同的標題創建一個新問題嗎?這仍然是同樣的問題。我已經提出了你的答案... – Flavius

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", '*') 

補丁歡迎!