Django: запустить процесс в фоновом потоке? - PullRequest
17 голосов
/ 04 марта 2010

Я пытаюсь понять, как запустить процесс в фоновом потоке в 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))

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

Ответы [ 4 ]

20 голосов
/ 10 августа 2012

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

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

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

Cheers

9 голосов
/ 01 декабря 2015

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

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 на всех ваших серверах не очень хорошая идея. Тогда не будет способа запустить отдельный процесс на каждом сервере. Вам могут понадобиться темы для обработки этого случая. Операции с файловой системой могут быть примером. Это маловероятно, и все же лучше использовать Celery с длительными процессами.

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

5 голосов
/ 04 марта 2010

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

3 голосов
/ 04 марта 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...