I can't reproduce your issue. In EC2 I set up two instances, one with a mongod which I forced to be primary, and one with a secondary and an arbiter. With PyMongo 2.1.1:
>>> c.host # Which instance has the primary right now?
>>> c.test.test.find_one()
{u'_id': ObjectId('5048f365923450f553000000')}
>>> # In AWS console, I stop the instance with the primary. The instance with secondary
>>> # and arbiter is still up, so secondary becomes new primary.
>>> c.test.test.find_one() # Expect first try to fail
Traceback (most recent call last)
pymongo/collection.py in find_one(self, spec_or_id, *args, **kwargs)
pymongo/cursor.py in next(self)
pymongo/cursor.py in _refresh(self)
pymongo/cursor.py in __send_message(self, message)
pymongo/connection.py in _send_message_with_response(self, message, _must_use_master, **kwargs)
pymongo/connection.py in __socket(self)
pymongo/connection.py in get_socket(self, host, port)
pymongo/connection.py in connect(self, host, port)
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.pyc in meth(name, self, *args)
timeout: timed out
>>> c.test.test.find_one() # Second try works as expected
{u'_id': ObjectId('5048f365923450f553000000')}
>>> c.host # New primary's instance
After PyMongo throws a timeout error, it reconnects and detects the new primary during the next operation. So we expect only one timeout after you stop an instance in EC2.