2015-05-27 2 views
0

На основе компонента SMTPD я написал собственный SMTP-сервер с авторизацией и т. Д. Последнее, что мне нужно сделать, это добавить синтаксический анализ сообщений в новый поток, когда он появится.Как создать новый поток python с классами?

Таким образом, мой компонент состоит из двух классов: SMTPServer и SMTPChannel. Он отлично работает в одном потоке, как это:

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) 

Вход выглядеть следующим образом:

[email protected] ~/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:<[email protected]*******>' 
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok' 
[2015-05-27 11:16:47] [MainThread] DEBUG: --> RCPT : 'TO:<[email protected]*******>' 
[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:<[email protected]*******>' 
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok' 
[2015-05-27 11:16:48] [MainThread] DEBUG: --> RCPT : 'TO:<[email protected]*******>' 
[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() 

Журнал выглядит следующим образом:

[email protected] ~/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):

+0

@abarnert, как я уже говорил, перед тем, как 'SMTPChannel' совпадает с https://hg.python.org/cpython/file/2.7/Lib/smtpd.py, за исключением того, что он переписан как автономный (проверка метода сообщения процесса добавлено) – user1692333

+0

Это похоже на проблему [XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Почему, по-вашему, вы хотите использовать потоки с приложением 'asynchat'? Что вы пытаетесь выполнить, и почему вы думаете, что нити помогут? Если вы можете это объяснить, возможно, мы сможем объяснить, как на самом деле делать то, что вы хотите. – abarnert

ответ

1

Вы не можете смешивать asyncore и темы, как это. Весь смысл приложения asyncore/asynchat заключается в том, что существует цикл событий вокруг select, который обрабатывает все ваши сокеты и совершает вызовы для различных обработчиков. Все это происходит в одном потоке. См. Введение в документацию asyncore, в которой объясняется это.

Запуск нового asynchat канала на другой поток не приносит пользы. Это означает, что он регистрируется в цикле событий из другого потока. (На самом деле это не потокобезопасно, поэтому вам просто повезло, если он работает.) После этого цикл событий и диспетчеризация обработчикам канала происходят в основном потоке.

Если вы хотите использовать многопоточность, не используйте asyncore. Если вы хотите использовать asyncore, не используйте многопоточность.

+0

Так как я понял, что если я использую 'asyncore/asynchat', мне не нужно думать о потоках, поскольку он имеет дело или мне нужно переписать все приложение, чтобы оно выполнялось быстрее без' asyncore/asynchat', но с потоками ? Извините, если я не настолько ясен, но я новичок в Python. – user1692333

+0

@ user1692333 Ну, это не касается самой _threads_; он рассматривает параллелизм по-другому (используя цикл событий). Переписывание его потоками, вероятно, не ускорилось бы (Al hough, это зависит от того, какую работу вы на самом деле делаете). Перезаписать его с помощью лучшего цикла событий может сделать его быстрее. Но на самом ли деле это слишком медленно? Если да, то какая часть делает это медленным? – abarnert

+0

Это не только скорость, но я получаю много писем с видео/файлами изображений, которые могут быть тяжелыми. Поэтому я просто хочу анализировать каждый параллельно, а не один за другим. – user1692333

Смежные вопросы