2016-07-25 3 views
1

У меня возникла проблема с обработкой более 2700 файлов. Это работает, если у меня есть немного файлов, таких как несколько сотен, и я предполагаю, что это связано с закрытием окон файлы, как в linux ulimit, могут быть определены по всей системе. Я уверен, что вещи не закрываются, и именно поэтому я получаю эту ошибку.Слишком много открытых файлов urllib

У меня есть функция, которая отправляет файл по почте:

def upload_photos(url_photo, dict, timeout): 
    photo = dict['photo'] 
    data_photo = dict['data'] 
    name = dict['name'] 
    conn = requests.post(url_photo, data=data_photo, files=photo, timeout=timeout) 
    return {'json': conn.json(), 'name': name} 

, который вызывается из петли список каталогов:

for photo_path in [p.lower() for p in photos_path]: 
     if ('jpg' in photo_path or 'jpeg' in photo_path) and "thumb" not in photo_path: 
      nr_photos_upload +=1 
    print("Found " + str(nr_photos_upload) + " pictures to upload") 
    local_count = 0 
    list_to_upload = [] 
    for photo_path in [p.lower() for p in photos_path]: 
     local_count += 1 
     if ('jpg' in photo_path or 'jpeg' in photo_path) and "thumb" not in photo_path and local_count > count: 
      total_img = nr_photos_upload 
      photo_name = os.path.basename(photo_path) 
      try : 
       photo = {'photo': (photo_name, open(path + photo_path, 'rb'), 'image/jpeg')} 
       try: 
        latitude, longitude, compas = get_gps_lat_long_compass(path + photo_path) 
       except ValueError as e: 
        if e != None: 
         try: 
          tags = exifread.process_file(open(path + photo_path, 'rb')) 
          latitude, longitude = get_exif_location(tags) 
          compas = -1 
         except Exception: 
          continue 
       if compas == -1: 
        data_photo = {'coordinate' : str(latitude) + "," + str(longitude), 
           'sequenceId'  : id_sequence, 
           'sequenceIndex' : count 
           } 
       else : 
        data_photo = {'coordinate' : str(latitude) + "," + str(longitude), 
           'sequenceId'  : id_sequence, 
           'sequenceIndex' : count, 
           'headers'   : compas 
           } 
       info_to_upload = {'data': data_photo, 'photo':photo, 'name': photo_name} 
       list_to_upload.append(info_to_upload) 
       count += 1 
      except Exception as ex: 
       print(ex) 
    count_uploaded = 0 
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: 
     # Upload feature called from here 
     future_to_url = {executor.submit(upload_photos, url_photo, dict, 100): dict for dict in list_to_upload} 
     for future in concurrent.futures.as_completed(future_to_url): 
      try: 
       data = future.result()['json'] 
       name = future.result()['name'] 
       print("processing {}".format(name)) 
       if data['status']['apiCode'] == "600": 

        percentage = float((float(count_uploaded) * 100)/float(total_img)) 
        print(("Uploaded - " + str(count_uploaded) + ' of total :' + str(
         total_img) + ", percentage: " + str(round(percentage, 2)) + "%")) 
       elif data['status']['apiCode'] == "610": 
        print("skipping - a requirement arguments is missing for upload") 
       elif data['status']['apiCode'] == "611": 
        print("skipping - image does not have GPS location metadata") 
       elif data['status']['apiCode'] == "660": 
        print("skipping - duplicate image") 
       else : 
        print("skipping - bad image") 
       count_uploaded += 1 
       with open(path + "count_file.txt", "w") as fis: 
        fis.write((str(count_uploaded))) 
      except Exception as exc: 
       print('%generated an exception: %s' % (exc)) 
+0

Таким образом, проблема заключается в simulatanious обработке слишком много файлов. Может быть, самый простой способ исправить это: не останавливайтесь, если есть какие-либо проблемы, но подождите несколько миллисекунд и повторите (будьте осторожны, чтобы избежать бесконечного цикла). В этом случае все файлы будут обработаны. – Ilya

+0

В обычных случаях редко бывает полезно загружать больше, чем несколько файлов одновременно, особенно когда вы забиваете один и тот же сервер. Уменьшите количество одновременных подключений. –

ответ

1

Вы можете установить _setmaxstdio в C, чтобы изменить номер файлов, которые можно открыть одновременно.

Для питона вы должны использовать win32file из pywin32 как:

import win32file 
win32file._setmaxstdio(1024) #set max number of files to 1024 

по умолчанию является 512. И убедитесь, что вы установите максимальное значение, которое вы установили, поддерживается вашей платформой.

Ссылка: https://msdn.microsoft.com/en-us/library/6e3b887c.aspx

+1

«Максимальное количество открытых файлов» - это тот предел, который в настоящее время достаточно высок, что должно заставлять вас подвергать сомнению ваш алгоритм, а не находить способы изменить предел ... –

+1

Этот вариант не работает и что Маттео сказал, это не Лучшая практика сделать что-то вроде этого – James

Смежные вопросы