2012-04-20 6 views
1

私はPython dict形式で何千もの行を含む多数の大きなファイルを持っています。私はjson.dumpsでjson文字列に変換しています。Python DictをマルチスレッドファッションのJSONに変換するにはどうすればいいですか

import json 
import ast 

mydict = open('input', 'r') 
output = open('output.json', "a") 

for line in mydict: 
     line = ast.literal_eval(line) 
     line = json.dumps(line) 
     output.write(line) 
     output.write("\n") 

これは完璧に機能しますが、これは単一のスレッド形式で行われます。物事をスピードアップするためにシステム内の残りのコアを利用する簡単な方法はありますか?

編集:私はマルチプロセッシング・ライブラリとここに始めた提案に基づいて

import os 
import json 
import ast 
from multiprocessing import Process, Pool 

mydict = open('twosec.in', 'r') 

def info(title): 
     print title 
     print 'module name:', __name__ 
     print 'parent process: ', os.getppid() 
     print 'process id:', os.getpid() 

def converter(name): 
     info('converter function') 
     output = open('twosec.out', "a") 
     for line in mydict: 
       line = ast.literal_eval(line) 
       line = json.dumps(line) 
       output.write(line) 
       output.write("\n") 

if __name__ == '__main__': 
     info('main line') 
     p = Process(target=converter, args=(mydict)) 
     p.start() 
     p.join() 

プールの出番私はかなり理解していない、あなたはより多くを説明できますか?

+0

を使用して、PNG形式にDICOMファイルを変換するプログラムの完全な例であります複数のスレッドを使用して*変換*を行います。 – poke

答えて

1

その1つの引数としてファイル名を取り、それが出力ファイルにJSONを書き込み機能に上記のコードをラップします。

multiprocessingモジュールからPoolオブジェクトを作成し、Pool.map()を使用して、すべてのファイルのリストと並行して機能を適用します。これにより、CPU上のすべてのコアが自動的に使用され、スレッドの代わりに複数のプロセスが使用されるため、グローバルインタプリタのロックには移行しません。

編集:プログラムのメイン部分をそうするように変更します。もちろん

if __name__ == '__main__': 
    files = ['first.in', 'second.in', 'third.in'] # et cetera 
    info('main line') 
    p = Pool() 
    p.map(convertor, files) 
    p.close() 

あなたはまた、入力された名前から出力名を導出するconvertor()を変更する必要があります!以下は

は、ここではボトルネックはおそらくI/Oであるので、私はあなたがから任意の利益を得るでしょう疑うImageMagickプログラムに

"Convert DICOM files to PNG format, remove blank areas." 

import os 
import sys # voor argv. 
import subprocess 
from multiprocessing import Pool, Lock 

def checkfor(args): 
    try: 
     subprocess.check_output(args, stderr=subprocess.STDOUT) 
    except CalledProcessError: 
     print "Required program '{}' not found! exiting.".format(progname) 
     sys.exit(1) 

def processfile(fname): 
    size = '1574x2048' 
    args = ['convert', fname, '-units', 'PixelsPerInch', '-density', '300', 
      '-crop', size+'+232+0', '-page', size+'+0+0', fname+'.png'] 
    rv = subprocess.call(args) 
    globallock.acquire() 
    if rv != 0: 
     print "Error '{}' when processing file '{}'.".format(rv, fname) 
    else: 
     print "File '{}' processed.".format(fname) 
    globallock.release() 

## This is the main program ## 
if __name__ == '__main__': 
    if len(sys.argv) == 1: 
     path, binary = os.path.split(sys.argv[0]) 
     print "Usage: {} [file ...]".format(binary) 
     sys.exit(0) 
    checkfor('convert') 
    globallock = Lock() 
    p = Pool() 
    p.map(processfile, sys.argv[1:]) 
    p.close() 
+0

私はあなたの提案に基づいて編集を行いましたが、それは単なるスタートですが、私はまだどこに実装するのかはわかりませんプール – secumind

+0

私はもう少し "上記"を試しましたが、それを働かせる。 Pool.map()をもっと使い方を説明できますか? – secumind

+0

イメージをパラレルに変換するために使用するスクリプトを例として追加しました。私はそれが役に立つと思う。デフォルトでは、Poolはコアを持つだけの数のワーカープロセスを作成することに注意してください。より多くのプロセスが必要な場合は、プールの作成時にそれを伝える必要があります。 documnetationを参照してください。 –

1

マルチスレッドからスピードアップを得る簡単な方法はわかりませんが、スピードアップが本当に必要なものなら、jsonの代わりにujsonパッケージを試してみることをおすすめします。基本的に無料で、私にとって非常に大きなスピードアップを生み出しました。通常のjsonパッケージと同じ方法で使用してください。

http://pypi.python.org/pypi/ujson/

+0

それはかなり速いjsonモジュールです:http://pushingtheweb.com/2011/03/ultra-fast-json-encoding-decoding-python/ – jdi

+0

私はujsonで少し改善を見ます、約3秒は1.23分を削りました200MBの変換。しかし、それは2TBファイルのほんの5分の節約です "はい、ファイルのいくつかは大きい" – secumind

+0

右、よく私はここにボトルネックがディスクI/Oであることを同意するでしょう。この問題で投げたプロセッサー数やアルゴリズムの数に関係なく、ここでスピードを向上させる唯一の方法は、SSDやRAID構成など、より高速な読み取り速度でハードドライブを取得することです。 –

関連する問題