我试图通过 Gevent 和 IMAP 从我的电子邮件创建消息的异步下载。我使用 Python 2.7.8 和 Gevent 1.1.1 。
self.connection = imaplib.IMAP4_SSL(self.hostname, self.port, **ssl_files)
...
rv, data = self.connection.search(None, "ALL")
numbers = [number for number in data[0].split()]
threads = [gevent.spawn(self._get_message, message) for message in numbers]
gevent.joinall(threads)
函数_get_message
有以下代码:
def _get_message(self, message_number):
logging.info("Message {0} called!".format(message_number))
rv, data = self.connection.fetch(message_number, '(RFC822)')
if not self.is_ok(rv): return
message = email.message_from_string(data[0][1])
但每次我都有这个错误:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\gevent\greenlet.py", line 534, in run
result = self._run(*self.args, **self.kwargs)
File "C:/Users/Eugene/PycharmProjects/Extract Email by Criteria/imap_email.py", line 108, in _get_message
rv, data = self.connection.fetch(message_number, '(RFC822)')
File "C:\Python27\lib\imaplib.py", line 456, in fetch
typ, dat = self._simple_command(name, message_set, message_parts)
File "C:\Python27\lib\imaplib.py", line 1088, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "C:\Python27\lib\imaplib.py", line 910, in _command_complete
typ, data = self._get_tagged_response(tag)
File "C:\Python27\lib\imaplib.py", line 1017, in _get_tagged_response
self._get_response()
File "C:\Python27\lib\imaplib.py", line 929, in _get_response
resp = self._get_line()
File "C:\Python27\lib\imaplib.py", line 1027, in _get_line
line = self.readline()
File "C:\Python27\lib\imaplib.py", line 1189, in readline
return self.file.readline()
File "C:\Python27\lib\socket.py", line 451, in readline
data = self._sock.recv(self._rbufsize)
File "C:\Python27\lib\site-packages\gevent\_sslgte279.py", line 455, in recv
return self.read(buflen)
File "C:\Python27\lib\site-packages\gevent\_sslgte279.py", line 314, in read
self._wait(self._read_event, timeout_exc=_SSLErrorReadTimeout)
File "C:\Python27\lib\site-packages\gevent\_socket2.py", line 173, in _wait
raise _socketcommon.ConcurrentObjectUseError('This socket is already used by another greenlet: %r' % (watcher.callback, ))
ConcurrentObjectUseError: This socket is already used by another greenlet: <bound method Waiter.switch of <gevent.hub.Waiter object at 0x02B1C558>>
<Greenlet at 0x2afe710: <bound method EmailImapConnection._get_message of <__main__.EmailImapConnection object at 0x02A63C50>>(4)> failed with ConcurrentObjectUseError
Github上的代码Gist:https://gist.github.com/gitex/0d9385fa3ab1d98f30713f6eeeab454f
我在开始时有monkey.patch_all()
。仅适用于第一个插槽,其余部分均已锁定。我假设套接字在 IMAP 中被阻止。我该如何解决这个问题?