2016-03-31 6 views
0

Мне нужно прочитать вложения файлов из сообщений электронной почты. Я хотел использовать менеджер контекста для управления ресурсами (соединение должно быть закрыто)Как использовать диспетчер контекста с исключениями

@contextmanager 
def some_f(): 
    conn = None 
    try: 
     for _ in xrange(CONNECTION_ERRORS_MAX): 
      try: 
       conn = POP3(self.pop3_host) 
       conn.user(self.pop3_user) 
       conn.pass_(self.pop3_password) 
       logger.debug('connected {}', conn.getwelcome()) 
       _, msg_ids, _ = conn.uidl() 
       yield (
        (msg_id, self.files_from_msg(conn, file_batch_id, msg_id)) 
        for msg_id, file_batch_id in 
        (ul.split(' ') for ul in msg_ids) 
        if not self.is_ignored(file_batch_id, msg_id) 
       ) 
      except socket.error as e: 
       if e.errno == errno.ECONNREFUSED: 
        pass 
       else: 
        raise e 
    finally: 
     if conn: 
      conn.quit() 

Так что эта функция должна сделать, это попытаться подключиться к серверу электронной почты, повторите п раз, если соединение было отказано, если другая ошибка сокета произошли затем ререйз. Если попытки повторной попытки исчерпаны, то повторное соединение отказалось от ошибки. После того, как потребитель будет потреблять все файлы с близким подключением. Прямо сейчас он дает генератору ошибку.

+0

Это что, 'contextlib.contextmanager'? – timgeb

+0

@timgeb да это – user1685095

+1

Если вы читаете [документы] (https://docs.python.org/3.4/library/contextlib.html?highlight=contextmanager#contextlib.contextmanager) для 'contextmanager', вы будете что функция диспетчера должна сначала выполнить какое-либо действие по настройке, затем перейти к «клиентскому» коду (т. е. блоку после оператора with), а затем выполнить некоторую очистку; оператор 'with' является, по сути, способом сэндвич-кода в пределах определенной предопределенной логики до и после. В вашем случае оператор yield находится внутри цикла 'for', что, вероятно, не является тем, что вы хотите. – SwiftsNamesake

ответ

0

Перестройте предложение try-except так, чтобы оно окружало минимальное количество вещей. В предложении except вы можете при необходимости continue, и если он не активирован, вы должны break из цикла for.