5

私はイメージを抽出しようとしている110のPDFを持っています。画像が抽出されたら、私は重複を削除し、4KB未満の画像を削除したいと思います。それを行うには私のコードは次のようになります。Pythonでマルチプロセッシングモジュールを正しく利用するには?

def extract_images_from_file(pdf_file): 
    file_name = os.path.splitext(os.path.basename(pdf_file))[0] 
    call(["pdfimages", "-png", pdf_file, file_name]) 
    os.remove(pdf_file) 

def dedup_images(): 
    os.mkdir("unique_images") 
    md5_library = [] 
    images = glob("*.png") 
    print "Deleting images smaller than 4KB and generating the MD5 hash values for all other images..." 
    for image in images: 
     if os.path.getsize(image) <= 4000: 
      os.remove(image) 
     else: 
      m = md5.new() 
      image_data = list(Image.open(image).getdata()) 
      image_string = "".join(["".join([str(tpl[0]), str(tpl[1]), str(tpl[2])]) for tpl in image_data]) 
      m.update(image_string) 
      md5_library.append([image, m.digest()]) 
    headers = ['image_file', 'md5'] 
    dat = pd.DataFrame(md5_library, columns=headers).sort(['md5']) 
    dat.drop_duplicates(subset="md5", inplace=True) 

    print "Extracting the unique images." 
    unique_images = dat.image_file.tolist() 
    for image in unique_images: 
     old_file = image 
     new_file = "unique_images\\" + image 
     shutil.copy(old_file, new_file) 

このプロセスにはしばらく時間がかかることができますので、私は、マルチスレッドに手を出すために始めました。私が何をしているのか分かりませんと私が言っていることを自由に解釈してください。私はこのプロセスがイメージの抽出に関して簡単に並列化できると思っていましたが、1つのファイルで多くのI/Oが実行されているため、どのように処理するのか分かりません。そこでここでは並列プロセスでの私の試みです:

if __name__ == '__main__': 
    filepath = sys.argv[1] 
    folder_name = os.getcwd() + "\\all_images\\" 
    if not os.path.exists(folder_name): 
     os.mkdir(folder_name) 
    pdfs = glob("*.pdf") 
    print "Copying all PDFs to the images folder..." 
    for pdf in pdfs: 
     shutil.copy(pdf, ".\\all_images\\") 
    os.chdir("all_images") 
    pool = Pool(processes=8) 
    print "Extracting images from PDFs..." 
    pool.map(extract_images_from_file, pdfs) 
    print "Extracting unique images into a new folder..." 
    dedup_images() 
    print "All images have been extracted and deduped." 

すべてが画像を抽出する際にうまく働いているようだが、それはすべてのめちゃくちゃ行きました。だからここに私の質問です:

1)私は正しく並列処理を設定していますか?
2)dedup_images()で8台のプロセッサをすべて使用しようとしますか?
3)紛失しているか、正しく行っていないことはありますか?

ありがとうございます!

編集ここで私は "haywire"を意味します。エラーは、このようなラインの束でスタート:

I/O Error: Couldn't open image If/iOl eE r'rSourb:p oICe/onOua l EdNrner'wot r Y:oo prCekon u Cliodmunan'gttey of1pi0e 
l2ne1 1i'4mS auogbiepl o2fefinrlaee e [email protected]'egSwmu abYipolor ekcn oaCm o Nupentwt y1Y -o18r16k11 8.C1po4nu gn3't4 
y7 5160120821143 3p4t7I 9/49O-8 88E78r81r.3op rnp:gt ' C 
3o-u3l6d0n.'ptn go'p 
en image file 'Ia/ ON eEwr rYoorr:k CCIoo/uuOln dtEnyr' rt1o 0ro2:p1 e1Cn4o uiolmidalng2'eft r m ' 
ai gpceoo emfn iapl teN e1'w-S 8uY6bo2pr.okpe nnCgao' u 
Nnetwy Y1o0r2k8 1C4o u3n4t7y9 918181881134 3p4t7 536-1306211.3p npgt' 
4-879.png' 
I/O Error: CoulId/nO' tE rorpoern: iCmoaugled nf'itl eo p'eub piomeangae fNielwe Y'oSrukb pCooeunnat yN e1w0 2Y8o1r 
4k 3C4o7u9n9t8y8 811032 1p1t4 3o-i3l622f pt 1-863.png' 

そして、このように複数のラインを持つより読みやすくなります:

I/O Error: Couldn't open image file 'pt 1-864.png' 
I/O Error: Couldn't open image file 'pt 1-865.png' 
I/O Error: Couldn't open image file 'pt 1-866.png' 
I/O Error: Couldn't open image file 'pt 1-867.png' 

これは文字化けの間で前後に行く、しばらくの間、繰り返されますエラーテキストと読み取り可能な

最後に、それはここにするために取得します。

コードが戻って拾うことを意味し、プロセスでの続く
Deleting images smaller than 4KB and generating the MD5 hash values for all other images... 
Extracting unique images into a new folder... 

。何がうまくいかないでしょうか?

+1

それは私にはよく見えます。あなたは、「干し草に行きました」についてより具体的になりますか? – strubbly

+0

@strubbly上記のエラー出力を追加しました。 – brittenb

+0

"私はマルチスレッドで叩き始めました。私が何をしているのかわからないと言って、自由に感じてください。"あなたと他の誰もが並行処理を始めます。 –

答えて

3

コードは基本的に問題ありません。

文字化けしたテキストは、異なるバージョンのI/O Errorメッセージをコンソールにインタリーブして書き込もうとするすべてのプロセスです。エラーメッセージはpdfimagesコマンドによって生成されています。おそらく、一度に2つを実行すると、一時ファイルを上回っているか、同じファイル名などを使用している可能性があります。

個別のpdfファイルごとに異なるイメージルートを使用してみてください。

+0

私はこの問題を効果的に解決したので、これを答えとして受け入れました。ルート名に任意の3桁の英数字コードを追加し、問題を完全に緩和しました。ありがとう! – brittenb

+0

クール - マルチプロセッシングでうまくやっています。あなたが呼んでいることは、一緒に走れるようにする必要があることに留意してください。ディレクトリやファイルなどのリソースを共有するときに競合する可能性があります。 – strubbly

3
  1. はい、Pool.mapは1つの引数をとり、各要素が最初の関数の引数として渡される関数をとります。
  2. いいえ、ここで書いたものはすべてextract_images_from_file()という本文以外の元のプロセスで実行されるためです。また、私はあなたがプロセスを使用していて、プロセッサではないことを指摘します。ハイパースレッディングが有効になっている8コアのIntel CPUを使用した場合、同時に16のプロセスを実行することができます。
  3. extract_images_from_file()が例外をスローすると、Pool全体が核となりますが、これはおそらくあなたが望むものではありません。これを防ぐために、そのブロックの周りに試してみることができます。

あなたが扱っている「ヘイワイヤー」の性質は何ですか?例外テキストは見えますか?

+0

質問にエラー出力を追加しました。 – brittenb

関連する問題