【问题标题】:How to run python script as daemon/cronjob in Django?如何在 Django 中将 python 脚本作为守护进程/cronjob 运行?
【发布时间】:2020-10-14 16:15:18
【问题描述】:

我已经开发了一个 Django 应用程序并尝试解决应该简单的问题......但是我阅读了更多关于此的内容,并且似乎更复杂。

我希望每次在 auth_user 中创建新用户帐户时都向新用户发送一封电子邮件。 我首先想到了信号,它可以工作,但当我执行 sql 脚本来创建用户帐户时却不行。

所以,我考虑过使用触发器和 Postgresql LISTEN/NOTIFY。 我在 auth_user insert 上创建了一个触发器,并使用此触发器执行了一个函数,该函数使用 perform pg_notify('new_user', NEW.username); 通知此事件

然后,我有一个 Python 脚本,它可以监听 new_user 信号并发送电子邮件。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# https://www.depesz.com/2012/06/13/how-to-send-mail-from-database/
# https://www.psycopg.org/docs/connection.html
# https://www.psycopg.org/docs/advanced.html#async-notify

import select
import psycopg2
import psycopg2.extensions
from django.core.mail import send_mail
import random, string
from django.contrib.auth.hashers import make_password

dbc = psycopg2.connect(database='db', host='localhost', port=5433, user='user', password='user')
dbc.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cur = dbc.cursor()
cur.execute('LISTEN new_user_handle')

while 1:
    if not select.select([dbc], [], [], 5) == ([], [], []):
        dbc.poll()
        while dbc.notifies:
            notify = dbc.notifies.pop()
            user_email = []
            password = generer_mot_de_passe(8)
            user_email.append('user@domain.fr')
            email = email_compte(user_email,notify.payload,password.get("plaintext"))


    def generer_mot_de_passe(length):
        """Générer une chaîne aléatoire de longueur fixe"""
        motDePasse = {}
        str = string.hexdigits
        password_plaintext = ''.join(random.choice(str) for i in range(length))
        password_crypt = make_password(password_plaintext)
        motDePasse['plaintext'] = password_plaintext
        motDePasse['pbkdf2'] = password_crypt
        return motDePasse


    # envoi d'email lors de la création d'un compte utilisateur
    def email_compte(user_email,identifiant,password): 

        subject = '[Moderato] Application Randomisation - Compte utilisateur '
        message = 'Test'
        email_from = 'webmaster@domain.fr'

        email = send_mail(subject, message, email_from , user_email)

        return None

这可行,但我读到这不是一个好方法,因为 PostgreSQL 会将所有尚未由所有 LISTENING 进程处理的 NOTIFY 排队,如果没有任何东西在听,它不会将它们排队。 所以——如果你的监听器死掉了——在它死去和重启之间发生的所有通知都会消失。

一些使用队列的建议。 所以我有一个 process_queue 表,每次创建用户帐户时都会更新。 现在,我需要在定期执行的“后台任务”(守护进程或 cronjob)中“扫描”这个 process_queue 表以发送电子邮件......

不知道该怎么做?

【问题讨论】:

    标签: django python-daemon


    【解决方案1】:

    如果需要 cronjobs/周期性任务或 django 中的异步任务,我建议使用 celery。检查celery-django

    【讨论】:

    • 我正在阅读有关芹菜的信息。我可以使用我的 postgresql 项目数据库作为代理吗?它在文档中被提及,但有人说它不推荐或不可能用于新的 Celery 版本......
    • 如果负载高,不建议使用数据库作为代理,但 postgresql 可以在 celery==5.0.0 版本上正常工作
    猜你喜欢
    • 2015-03-21
    • 2011-01-03
    • 2013-10-14
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2013-09-14
    相关资源
    最近更新 更多