Как загрузить кучу файлов с модулем Python запросов - PullRequest
3 голосов
/ 13 июля 2020

Когда я использую модуль requests для загрузки как минимум 400 файлов одним запросом, я получал ошибку Too many open files в системе macOS.

Я пробовал ulimit -n 20000.

Также проверено:

  • sysctl kern.maxfiles получил 98304
  • sysctl kern.maxfilesperproc получил 49152

Однако это не сработало.

Вот мой код:

import os
import requests


url = 'http://127.0.0.1:8000/api/upload'
file_path = '/Users/BonJu/Projects/downloads'
file_list = os.listdir(file_path)
files = []
for file in file_list:
    try:
        source = open(os.path.join(file_path, file), 'rb')
        files.append(('file', source))

    except Exception as e:
        print('File: %s, Error: %s' % (file, e.__str__()))
        continue

response = requests.post(url=url, data={'uploader': 'admin'}, files=files)

Результат терминала:

File: test_252.docx, Error: [Errno 24] Too many open files: '/Users/BonJu/Projects/downloads/test_252.docx'
File: test_253.docx, Error: [Errno 24] Too many open files: '/Users/BonJu/Projects/downloads/test_253.docx'
File: test_254.docx, Error: [Errno 24] Too many open files: '/Users/BonJu/Projects/downloads/test_254.docx'
...
File: test_418.docx, Error: [Errno 24] Too many open files: '/Users/BonJu/Projects/downloads/test_418.docx'

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

Есть ли решение этой ситуации?

Решение

Я наконец настроил свой API, чтобы сохранить временный файл для хранения журналов загрузки и передать параметр status для управления окончательным выводом.

мой код:

payload = {
    'status': 'finish',
    'uploader': 'admin'
}
response = requests.post(url=url, data=payload, files=files)

API:

@api_view(['post'])
def upload(request, debug, api_version):
    status = request.POST.get('status')
    file_list = request.FILES.getlist('file')

    if status == 'finish':
        # open the temp file and insert the last logs then output
        
    else:
        # create/insert the logs and save to a temp file

    return Response({'status': status, 'files': file_list})

1 Ответ

1 голос
/ 13 июля 2020

Я бы посоветовал создать из них один tar файл.

или закрыть файлы после прочтения их содержимого (вместо того, чтобы оставлять их файловый дескриптор открытым до тех пор, пока вы не отправите запрос

...