2013-12-11 5 views
5

以下のコードのsaveData関数を同時に実行します。しかし、その代わりに、SaveDataを最初の実行後に、私はエラーを得た:複数のスレッドをPythonで起動する

Traceback (most recent call last): 
    File "preProcess.py", line 70, in <module> 
    run()   
    File "preProcess.py", line 61, in run 
    thread.start_new_thread(saveData(slice1, slice2, slice3, dset), ("Thread-" + str(i), 1,)) 
TypeError: first arg must be callable 

私のコードは

#!/usr/bin/env python 
import sys 

import numpy as np 
import h5py 
import scipy 
from PIL import Image 
import timeit 
import thread 

import matplotlib.pyplot as plt 

def saveImage(array, filename): 
    fig=plt.figure(figsize=(4,3)) 
    ax=fig.add_subplot(1,1,1) 
    plt.axis('off') 
    p = plt.imshow(array) 
    p.set_cmap('gray') 
    extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) 
    plt.savefig(filename, bbox_inches=extent) 

def saveData(value1, value2, value3, dset): 
    filename = "tomo1_" + str(value1) + ".png" 
    data = dset[value1::] 
    saveImage(data, filename) 
    filename = "tomo2_" + str(value2) + ".png" 
    data = dset[:value2:] 
    saveImage(data, filename) 
    filename = "tomo3_" + str(value3) + ".png" 
    data = dset[::value3] 
    saveImage(data, filename) 

def run(): 

    # Reopen the file and dataset using default properties. 
    f = h5py.File(sys.argv[1]) 
    dset = f[sys.argv[2]] 

    dim1 = len(dset) 
    dim2 = len(dset[0]) 
    dim3 = len(dset[0][0]) 

    slice1 = 0 
    slice2 = 0 
    slice3 = 0 
    factor1 = dim1/48 
    factor2 = dim2/48 
    factor3 = dim3/48 
    tic=timeit.default_timer() 
    for i in range(0,48): 
    thread.start_new_thread(saveData(slice1, slice2, slice3, dset), ("Thread-" + str(i),  1,)) 
    slice1 = slice1 + factor1 
    slice2 = slice2 + factor2 
    slice3 = slice3 + factor3 

    toc=timeit.default_timer() 
    print "elapsed time: " + str(toc - tic) 

if __name__ == "__main__": 
    run()   

である私は、同時にSaveDataを機能48回実行したいと思います。 私は間違っていますか?

答えて

8

Gryphiusが指摘したように:あなたはstart_new_threadsaveDataを実行するのではなくthread.start_new_threadに普通の引数として、あなたの関数を使用しないでください!

理由は、thread.start_new_threadがスレッドであなたのために関数を実行するということです。だから、(それを実行せずに)引数としてだけでなく、機能を渡すために持っているだけでなく、あなたの関数の引数:ご覧のとおり、あなたの関数の引数はタプルとして渡され

thread.start_new_thread(saveData,(slice1,slice2,slice3,dset),("Thread-"+str(i),1,)) 

サイドノート: このイディオムは、関数を呼び出すのではなく、その引数と共に渡すというイディオムも、イベント処理関数:コールバックにあります。

threadの代わりにThreadingパッケージを使用することを検討してください。これははるかに洗練されており、より自由で機能的です。

+0

補足として:plsはグリフィウスの回答を受け入れます、彼はより速く正確でした、私はちょっと精巧でした;-) –

+0

あなたは問題を詳細に説明し、有益な情報を追加しました。あなたの答えは受け入れられるべきです。 – Gryphius

4

thread.start_new_threadのapiドキュメントをよく読んでください。最初の引数は呼び出し可能であると予想していますので、saveData(slice1, slice2, slice3, dset)の代わりにsaveDataと入力してください。 2番目の引数は、関数の引数を持つタプルです。

試してみてください。

thread.start_new_thread(saveData,(slice1, slice2, slice3, dset)) 
関連する問題