2017-08-14 31 views
1

我完全不熟悉Python,我通常會做Ruby或JS。但是我需要在運行Python的系統上編寫基準測試腳本。我想要做的是創建一個小腳本,獲取文件大小和線程數,並寫入隨機緩衝區。這是我2小時擺弄後得到:Python:AttributeError:無法醃製本地對象'writeBuf。 <locals> .write'

from multiprocessing import Pool 
import os, sys 

def writeBuf(buf): 
    def write(n): 
     f = open(os.path.join(directory, 'n' + str(n)), 'w') 
     try: 
      f.write(buf) 
      f.flush() 
      os.fsync(f.fileno) 
     finally: 
      f.close() 
    return write 

if __name__ == '__main__': 
    targetDir = sys.argv[1] 
    numThreads = int(sys.argv[2]) 
    numKiloBytes = int(sys.argv[3]) 
    numFiles = int(102400/numKiloBytes) 

    buf = os.urandom(numKiloBytes * 1024) 

    directory = os.path.join(targetDir, str(numKiloBytes) + 'k') 
    if not os.path.exists(directory): 
     os.makedirs(directory) 

    with Pool(processes=numThreads) as pool: 
     pool.map(writeBuf(buf), range(numFiles)) 

但它引發錯誤:AttributeError: Can't pickle local object 'writeBuf.<locals>.write'

我以前曾嘗試使用write沒有關閉,但是當我試圖定義我得到了一個錯誤__name__ == '__main__'部分內部的功能。省略if也會導致錯誤,並且我知道Pool需要它才能工作。

什麼應該只是一個小腳本變成了一個巨大的磨難,任何人都可以指出我正確的方式嗎?

回答

2

理論上,python不能泡菜的功能。 (詳情請參閱Can't pickle Function

實際上,python使用了一個函數的名稱和模塊,以便傳遞一個函數。就你而言,你試圖傳遞的函數是由writeBuf返回的局部變量。

相反:

  1. 取出writeBuf包裝。
  2. 請勿使用write的關閉(bufdirectory),而應將其所需的所有內容作爲參數提供給write

結果:

def write(args): 
    directory, buf, n = args 

    with open(os.path.join(directory, 'n' + str(n)), 'w') as f: 
     # might as well use with-statements ;) 
     f.write(buf) 
     f.flush() 
     os.fsync(f.fileno) 

if __name__ == '__main__': 
    ... 

    with Pool(processes=numThreads) as pool: 
     nargs = [(directory, buf, n) for n in range(numFiles)] 
     pool.map(write, nargs) 
相關問題