OSError: [Errno 24] Слишком много открытых файлов при загрузке 9000+ файлов csv через админку Django

У меня возникли трудности с загрузкой файлов csv, содержащих данные для заполнения базы данных моего проекта Django. Я обслуживаю свой проект, используя Django 3.1 и Gunicorn, если это важно. Я обратился к нескольким постам на stack overflow по тому же вопросу, но ни один из них не решил эту проблему. Просто перечислим шаги, которые я предпринял для решения этой проблемы:

  • Запустил ulimit -n 50000 в терминале, чтобы увеличить максимальное количество файлов, которые могут быть открыты, как было предложено в этом посте .
  • Использовал ulimit -n, чтобы найти максимальное количество файлов, которые могут быть открыты и изменил конфигурацию этого предела в файле limits.conf, как было предложено в этом посте , чтобы изменить системные ограничения. Я подтвердил это изменение, запустив ulimit -a
  • .
  • Я полагал, что это может быть проблема с памятью и что Linux ограничивает максимальный объем доступного пространства на куче, поэтому я изменил конфигурацию и для этого. К счастью, это не было проблемой памяти, так как использование оперативной памяти было чрезвычайно стабильным, согласно моей панели управления
  • .

Вот код, связанный с моей проблемой:

admin.py

class CsvImportForm(forms.Form):
    csv_upload = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

@admin.register(dummyClass)
class dummyClassAdmin(admin.ModelAdmin):
    search_fields = search fields
    list_display = stuff to display in a list
    list_filter = thing that filters objects
    prepopulated_fields = prepopulated field

@csrf_exempt
def get_urls(self):
    urls = super().get_urls()
    new_urls = [path('upload-csv/', self.upload_csv),]
    return new_urls + urls

@csrf_exempt
def upload_epcsv(self, request):

    if request.method == "POST":
        csv_files = request.FILES.getlist('csv_upload')
        errors = []
        for csv_file in csv_files:
            if not(csv_file.name.endswith('.csv') or  csv_file.name.endswith('.xlsx')):
                messages.warning(request, 'The wrong file type was uploaded')
                return HttpResponseRedirect(request.path_info)

            csv_data = None
            if csv_file.name.endswith('.xlsx'):
                csv_data = pd.read_excel(csv_file, sheet_name=0, engine='openpyxl')
            else:
                csv_data = pd.read_csv(csv_file)
            csv_data.fillna("https://www.a.com", inplace=True)
        
            
            *Insert code that parses through dataframe and populates fields in database with data



        url = reverse('admin:index')
        return HttpResponseRedirect(url)

    form = CsvImportForm()
    data = {"form": form}
    return render(request, "admin/csv_upload.html", data)

Вот трассировка ошибки:

Изменили имена путей в целях конфиденциальности

Похоже, что проблема в том, что pd.read_csv(csv_file) не закрывается csv_file, тип которого UploadedFile. Эти открытые файлы никогда не закрываются и в результате происходит утечка.

Вы можете попробовать войти в систему csv_data.closed и посмотреть, открыта ли она еще.

Решения:

  1. (Рекомендуем) Используйте временный_путь_файла при чтении, он закроет файл после чтения.
  2. Закройте его самостоятельно csv_file.close() наконец.
Вернуться на верх