Python Django多处理错误:“AttributeError:无法pickle本地对象'Command.handle。<locals> .f'”

时间:2018-01-01 02:38:52

标签: python django multiprocessing

我正在使用python 3.6 django 1.11 windows10并尝试使用多处理发送电子邮件。

收件人连接到数据库(django模型),电子邮件内容表单是html(由django get_template),也使用get_connection发送多封电子邮件。我正在尝试的是使用多处理来加速发送速率。

我的代码在这里

from django.core.management.base import BaseCommand
from django.core.mail import get_connection, EmailMessage
from django.template.loader import get_template

from multiprocessing import Pool

from sending.models import Subscriber


class Command(BaseCommand):
    def handle(self, *args, **options):

        connection = get_connection()

        recipients = [i.email for i in Subscriber.objects.all()]
        num = Subscriber.objects.count()

        subject = 'Multiprocessing trying 1'
        body = get_template('Newsletter20171229.html').render()
        from_email = 'info@modoodoc.com'


        def send(i):
            msg = EmailMessage(subject, body, from_email, [recipients[i]])
            msg.content_subtype = 'html'

            print("Sending email to: " + recipients[i] + " No: " + str(i))
            connection.send_messages([msg])
            print("Complete.")

        pool = Pool(processes=2)
        pool.map(send, range(0, num))


        print("Mail have just sent. The program is going to end.")
        connection.close()

我有这样的错误。

  File "c:\python36-32\Lib\multiprocessing\connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "c:\python36-32\Lib\multiprocessing\reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
AttributeError: Can't pickle local object 'Command.handle.<locals>.f'

如何解决这个问题?

谢谢。

1 个答案:

答案 0 :(得分:0)

您必须从send(以及handle类)中取出本地函数Command,并将放在模块的顶层,到unix_socket_directories option

对于subjectbodyfrom_email等封闭变量,您可以将它们捆绑在tuple中并将tuple作为单个传递send的论点。或者更好的是,在msg之外创建send个对象,并将msg列表传递给pool.map()

msg_list = [EmailMessage(subject, body, from_email, [recipients[i]])
            for i in range(0, num)]

for msg in msg_list
    msg.content_subtype = 'html'

pool = Pool(processes=2)
pool.map(send, msg_list)

其中模块级 send函数的定义如下:

def send(msg):
    print("Sending email to: {}".format(msg.recipients()[0]))
    connection.send_messages([msg])
    print("Complete.")