2016-04-11 13 views
1

サムネイルを作成して画像を保存するには、次のコードがあります。しかし、約1000アイテム後には、エラー番号too many open filesが発生します。これはどこから来たのですか?そしてコードをどのように修正すればよいでしょうか?subprocess.callを使用すると「開いているファイルが多すぎます」

def download_file(url, extension='jpg'): 
    """ Download a large file. Return path to saved file. 
    """ 
    req = requests.get(url) 
    if not req.ok: 
     return None 

    guid = str(uuid.uuid4()) 
    tmp_filename = '/tmp/%s.%s' % (guid, extension) 
    with open(tmp_filename, 'w') as f: 
     for chunk in req.iter_content(chunk_size=1024): 
      if chunk: 
       f.write(chunk) 
       f.flush() 
    return tmp_filename 


def update_artwork_item(item): 

    # Download the file 
    tmp_filename = util.download_file(item.artwork_url) 

    # Create thumbs 
    THUMB_SIZES = [(1000, 120), (1000, 30)] 
    guid = str(uuid.uuid4()) 
    S3_BASE_URL = 'https://s3-us-west-1.amazonaws.com/xxx/' 

    try: 

     for size in THUMB_SIZES: 
      outfile = '%s_%s.jpg' % (guid, size[1]) 
      img = Image.open(tmp_filename).convert('RGB') 
      img.thumbnail(size, Image.ANTIALIAS) 
      img.save(outfile, "JPEG") 
      s3_cmd = '%s %s premiere-avails --norr --public' % (S3_CMD, outfile) ## doesn't work half the time 
      x = subprocess.check_call(shlex.split(s3_cmd)) 
      if x: raise 
      subprocess.call(['rm', outfile], stdout=FNULL, stderr=subprocess.STDOUT) 

    except Exception, e: 

     print '&&&&&&&&&&', Exception, e 

    else: 
     # Save the artwork icons 
     item.artwork_120 = S3_BASE_URL + guid + '_120.jpg' 
     item.artwork_30 = S3_BASE_URL + guid + '_30.jpg' 

     # hack to fix parallel saving 
     while True: 
      try: 
       item.save() 
      except Exception, e: 
       print '******************', Exception, e 
       time.sleep(random.random()*1e-1) 
       continue 
      else: 
       subprocess.call(['rm', tmp_filename], stdout=FNULL, stderr=subprocess.STDOUT) 
       break 
+0

subprocess.call()の後にimg.close()を追加しようとしましたか? – Janekmuric

+0

問題を引き起こしている可能性のある場所がいくつかあります: 1) 'util.download_file'を確認し、http(s)リクエストを閉じていることを確認します。 2) 'img.save(outfile、" JPEG ")がファイルを閉じていることを確認してください。 –

+0

@CoryShay更新された質問を 'download_file()'関数で参照してください。 – David542

答えて

0

subprocess.callの使用はほぼ確実です。 subprocess.callは非同期で、パイプオブジェクトを返します。パイプオブジェクトは閉じられたものです。 (See the documentation)。つまり、subprocess.callを呼び出すたびに新しいパイプオブジェクトが返され、最終的にはファイルハンドルが足りなくなるということです。

最も簡単なことは、Unix rmコマンドにパイプするのではなく、os.removeを呼び出してPythonからファイルを削除するだけです。 check_callは同期的で、閉じなければならないファイルオブジェクトを返さないため、check_callの使用は大丈夫です。

関連する問題