如何用类创建新的python线程?

时间:2015-05-27 08:28:05

标签: python multithreading

SMTPD组件的基础上,我使用授权等编写了自己的SMTP服务器......我需要做的最后一件事是在新线程到来时添加消息解析。

所以我的组件包含两个类:SMTPServerSMTPChannel。它在这样的一个线程中完美地运行:

def handle_accept(self):
    pair = self.accept()

    if pair is not None:
        conn, addr = pair

        logging.info('Incoming connection from ' + str(addr))

        channel = SMTPChannel(config, conn, addr)

日志看起来像这样:

kiril@kiril-X501A1 ~/www/py_email $ python SMTPServer.py
[2015-05-27 11:15:57] [MainThread] INFO: Server started at 192.168.0.103:1026
[2015-05-27 11:16:46] [MainThread] INFO: Incoming connection from ('192.168.0.46', 52423)
[2015-05-27 11:16:46] [MainThread] DEBUG: <-- '220 SMTP Server 0.1 ESMTP'
[2015-05-27 11:16:46] [MainThread] DEBUG: --> EHLO : '*******'
[2015-05-27 11:16:46] [MainThread] DEBUG: <-- '250-SMTP Server 0.1 ESMTP Hello *******\n250-SIZE 20480000\n250 AUTH PLAIN LOGIN CRAM-MD5'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> AUTH : 'PLAIN AGFkbWluADEyMzQ='
[2015-05-27 11:16:47] [MainThread] INFO: ('192.168.0.46', 52423) successfully authenticated
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '235 Authentication successful.'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> MAIL : 'FROM:<reply@*******>'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> RCPT : 'TO:<destination@*******>'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> DATA
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '354 End data with <CR><LF>.<CR><LF>'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> QUIT
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '221 Bye'
[2015-05-27 11:16:47] [MainThread] INFO: Incoming connection from ('192.168.0.46', 52422)
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '220 SMTP Server 0.1 ESMTP'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> EHLO : '*******'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250-SMTP Server 0.1 ESMTP Hello *******\n250-SIZE 20480000\n250 AUTH PLAIN LOGIN CRAM-MD5'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> AUTH : 'PLAIN AGFkbWluADEyMzQ='
[2015-05-27 11:16:48] [MainThread] INFO: ('192.168.0.46', 52422) successfully authenticated
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '235 Authentication successful.'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> MAIL : 'FROM:<reply@*******>'
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> RCPT : 'TO:<destination@*******>'
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> DATA
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '354 End data with <CR><LF>.<CR><LF>'
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> QUIT
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '221 Bye'

但是当我添加这样的线程时:

def handle_accept(self):
    pair = self.accept()

    if pair is not None:
        conn, addr = pair

        logging.info('Incoming connection from ' + str(addr))

        new_thread = threading.Thread(target=SMTPChannel, args=(config, conn, addr,))
        new_thread.start()

日志如下所示:

kiril@kiril-X501A1 ~/www/py_email $ python SMTPServer.py
[2015-05-27 11:23:29] [MainThread] INFO: Server started at 192.168.0.103:1026
[2015-05-27 11:23:49] [MainThread] INFO: Incoming connection from ('192.168.0.46', 52414)
[2015-05-27 11:23:49] [Thread-1  ] DEBUG: <-- '220 SMTP Server 0.1 ESMTP'
[2015-05-27 11:23:49] [MainThread] DEBUG: --> EHLO : '*****'
[2015-05-27 11:23:49] [MainThread] DEBUG: <-- '250-SMTP Server 0.1 ESMTP Hello ********\n250-SIZE 20480000\n250 AUTH PLAIN LOGIN CRAM-MD5'
[2015-05-27 11:23:49] [MainThread] DEBUG: --> AUTH : 'PLAIN AGFkbWluADEyMzQ='
[2015-05-27 11:23:49] [MainThread] INFO: ('192.168.0.46', 52414) successfully authenticated

正如您所看到Thread-1只触发一次,然后所有消息都会回到主线程......可能它有一些东西可以处理类扩展为class MerlinSMTPServer(asyncore.dispatcher):class SMTPChannel(asynchat.async_chat): < / p>

1 个答案:

答案 0 :(得分:1)

你不能混合asyncore和这样的线程。 asyncore / asynchat应用程序的重点是select周围有一个事件循环来处理所有套接字,并调用各种处理程序。这一切都发生在一个线程上。请参阅asyncore文档的介绍,该文档对此进行了解释。

在另一个线程上启动新的asynchat频道没有任何好处。这只意味着它从另一个线程的事件循环中注册自己。 (这实际上并不是线程安全的,所以如果它有效,你就会变得幸运。)之后,事件循环和调度到通道的处理程序都发生在主线程上。

如果您想使用多线程,请不要使用asyncore。如果您想使用asyncore,请不要使用多线程。