Django: начать процесс в фоновом потоке?

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

Вот код, который у меня есть. В принципе, мне бы хотелось, чтобы start_processing начинался, как только срабатывала функция success. Однако start_processing - это функция, которая может занять несколько минут или не работать (зависит от внешней службы, над которой у меня нет контроля), и я не хочу, чтобы пользователю приходилось ждать, чтобы она завершилась успешно перед представлением представления. ( "Успех", насколько это возможно, не зависит от результата start_processing, я единственный человек, которому нужно беспокоиться, если он терпит неудачу.)

def success(request, filepath):
    start_processing(filepath)
    return render_to_response('success.html', context_instance = RequestContext(request))

Из Googling, который я сделал, большинство людей полагают, что фоновые потоки не используются в Django, и вместо этого задача cron более подходит. Но мне бы очень хотелось, чтобы start_processing начинался, как только пользователь добирался до функции успеха, а не ожидал, пока работа cron запустится. Есть ли способ сделать это?

Ответы

Ответ 1

Я не уверен, что для этого вам нужен поток. Похоже, вы просто хотите запустить процесс, поэтому загляните в модуль subprocess.

Ответ 2

Если вам действительно нужен быстрый взлом, просто запустите процесс, используя subprocess.

Но я бы не рекомендовать нерест процесса (или даже потока), особенно если ваш веб-сайт является общедоступным: в случае высокой нагрузки (что может быть "естественным" или результатом тривиальная атака DoS), вы будете создавать множество процессов или потоков, которые в конечном итоге будут использовать все ваши системные ресурсы и убить ваш сервер.

Вместо этого я бы рекомендовал использовать сервер заданий: я использую CeleryRedis в качестве бэкэнд), это очень просто и отлично работает. Вы можете проверить многие другие серверы заданий, такие как RabbitMQ или Gearman. В вашем случае сервер задания может быть переполнен: вы можете просто запустить Redis и использовать его в качестве легкого сервера сообщений. Здесь пример, как это сделать.

Приветствия

Ответ 3

Если кто-то действительно хочет запустить другой поток

def background_process():
    import time
    print("process started")
    time.sleep(100)
    print("process finished")

def index(request):
    import threading
    t = threading.Thread(target=background_process, args=(), kwargs={})
    t.setDaemon(True)
    t.start()
    return HttpResponse("main thread content")

Сначала это ответ будет возвращать, а затем распечатать "завершенный процесс" на консоли. Таким образом, пользователь не столкнется с какой-либо задержкой.

Использование сельдерея определенно является лучшим решением. Однако установка Celery может быть ненужной для очень небольшого проекта с ограниченным сервером и т.д.

Вам также может потребоваться использование потоков в большом проекте. Потому что запуск Celery на всех ваших серверах - это не очень хорошая идея. Тогда не будет способа запустить отдельный процесс на каждом сервере. Для обработки этого случая вам понадобятся потоки. Примером могут служить операции с файловой системой. Это не очень вероятно, хотя и лучше использовать сельдерей с длительными процессами.

Используйте разумно.

Ответ 4

IIUC. Проблема заключается в том, что для процесса веб-сервера могут не нравиться дополнительные длительные потоки, они могут убивать/запускать серверные процессы по мере увеличения спроса и т.д. и т.д.

Вероятно, вам лучше взаимодействовать с внешним процессом обслуживания для этого типа обработки, а не внедрять его в процесс wsgi/fastcgi веб-сервера.

Если единственное, что вы отправляете, это путь к файлу, для этого приложения-приложения должно быть довольно легко написать.