【问题标题】:Pymongo KeyError: '$err' MongoDB AtlasPymongo KeyError: '$err' MongoDB Atlas
【发布时间】:2017-09-27 09:22:45
【问题描述】:

我正在关注这个https://www.mongodb.com/blog/post/getting-started-with-python-and-mongodb 介绍性教程。我可以使用 mongo shell 连接到集群,但不能使用 pymongo(Python:3.6.1,Pymongo 3.4.0)。 Pymongo 可以在本地 mongodb 上正常工作。问题是什么?以下是我得到的异常:

----------------------------------------------------------------------
-----
KeyError                                  Traceback (most recent call 
last)
<ipython-input-22-1c9d47341338> in <module>()
----> 1 server_status_result = db.command('serverStatus')
      2 pprint(server_status_result)

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/database.py in command(self, command, value, check, 
allowable_errors, read_preference, codec_options, **kwargs)
489         """
490         client = self.__client
--> 491         with client._socket_for_reads(read_preference) as 
(sock_info, slave_ok):
492             return self._command(sock_info, command, slave_ok, 
value,
493                                  check, allowable_errors, 
read_preference,

/usr/lib/python3.6/contextlib.py in __enter__(self)
 80     def __enter__(self):
 81         try:
---> 82             return next(self.gen)
 83         except StopIteration:
 84             raise RuntimeError("generator didn't yield") from None

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/mongo_client.py in _socket_for_reads(self, 
read_preference)
857         topology = self._get_topology()
858         single = topology.description.topology_type == 
TOPOLOGY_TYPE.Single
--> 859         with self._get_socket(read_preference) as sock_info:
860             slave_ok = (single and not sock_info.is_mongos) or (
861                 preference != ReadPreference.PRIMARY)

/usr/lib/python3.6/contextlib.py in __enter__(self)
 80     def __enter__(self):
 81         try:
---> 82             return next(self.gen)
 83         except StopIteration:
 84             raise RuntimeError("generator didn't yield") from None

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/mongo_client.py in _get_socket(self, selector)
823         server = self._get_topology().select_server(selector)
824         try:
--> 825             with server.get_socket(self.__all_credentials) as 
sock_info:
826                 yield sock_info
827         except NetworkTimeout:

/usr/lib/python3.6/contextlib.py in __enter__(self)
 80     def __enter__(self):
 81         try:
---> 82             return next(self.gen)
 83         except StopIteration:
 84             raise RuntimeError("generator didn't yield") from None

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/server.py in get_socket(self, all_credentials, 
checkout)
166     @contextlib.contextmanager
167     def get_socket(self, all_credentials, checkout=False):
--> 168         with self.pool.get_socket(all_credentials, checkout) 
as sock_info:
169             yield sock_info
170 

/usr/lib/python3.6/contextlib.py in __enter__(self)
 80     def __enter__(self):
 81         try:
---> 82             return next(self.gen)
 83         except StopIteration:
 84             raise RuntimeError("generator didn't yield") from None

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/pool.py in get_socket(self, all_credentials, 
checkout)
790         sock_info = self._get_socket_no_auth()
791         try:
--> 792             sock_info.check_auth(all_credentials)
793             yield sock_info
794         except:

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/pool.py in check_auth(self, all_credentials)
510 
511             for credentials in cached - authset:
--> 512                 auth.authenticate(credentials, self)
513                 self.authset.add(credentials)
514 

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/auth.py in authenticate(credentials, sock_info)
468     mechanism = credentials.mechanism
469     auth_func = _AUTH_MAP.get(mechanism)
--> 470     auth_func(credentials, sock_info)
471 
472 

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/auth.py in _authenticate_default(credentials, 
sock_info)
448 def _authenticate_default(credentials, sock_info):
449     if sock_info.max_wire_version >= 3:
--> 450         return _authenticate_scram_sha1(credentials, 
sock_info)
451     else:
452         return _authenticate_mongo_cr(credentials, sock_info)

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/auth.py in _authenticate_scram_sha1(credentials, 
sock_info)
227                ('conversationId', res['conversationId']),
228                ('payload', Binary(client_final))])
--> 229     res = sock_info.command(source, cmd)
230 
231     parsed = _parse_scram_response(res['payload'])

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/pool.py in command(self, dbname, spec, slave_ok, 
read_preference, codec_options, check, allowable_errors, check_keys, 
read_concern, write_concern, parse_write_concern_error, collation)
422         # Catch socket.error, KeyboardInterrupt, etc. and close 
ourselves.
423         except BaseException as error:
--> 424             self._raise_connection_failure(error)
425 
426     def send_message(self, message, max_doc_size):

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/pool.py in _raise_connection_failure(self, error)
550             _raise_connection_failure(self.address, error)
551         else:
--> 552             raise error
553 
554     def __eq__(self, other):

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/pool.py in command(self, dbname, spec, slave_ok, 
read_preference, codec_options, check, allowable_errors, check_keys, 
read_concern, write_concern, parse_write_concern_error, collation)
417                            read_concern,
418                            
parse_write_concern_error=parse_write_concern_error,
--> 419                            collation=collation)
420         except OperationFailure:
421             raise

/home/tim/.virtualenvs/main/lib/python3.6/site-p 
ackages/pymongo/network.py in command(sock, dbname, spec, slave_ok, 
is_mongos, read_preference, codec_options, check, allowable_errors, 
address, check_keys, listeners, max_bson_size, read_concern, 
parse_write_concern_error, collation)
108         response = receive_message(sock, 1, request_id)
109         unpacked = helpers._unpack_response(
--> 110             response, codec_options=codec_options)
111 
112         response_doc = unpacked['data'][0]

/home/tim/.virtualenvs/main/lib/python3.6/site-
packages/pymongo/helpers.py in _unpack_response(response, cursor_id, 
codec_options)
126         # Fake the ok field if it doesn't exist.
127         error_object.setdefault("ok", 0)
--> 128         if error_object["$err"].startswith("not master"):
129             raise NotMasterError(error_object["$err"], 
error_object)
130         elif error_object.get("code") == 50:

KeyError: '$err'

【问题讨论】:

    标签: python mongodb pymongo pymongo-3.x mongodb-atlas


    【解决方案1】:

    我相信这是一个 Atlas 错误,我已向团队报告了它。错误是,如果您未能登录 Atlas,因为您的用户名或密码不正确,它的回复方式会使 PyMongo 抛出 KeyError 而不是正确的 OperationFailure("auth failed")

    但是,如果您使用用户名和密码正确格式化连接字符串,PyMongo 确实可以与 Atlas 一起使用。确保您的用户名和密码是 URL 引用的。将您的用户名和密码替换为此 Python 代码:

    from urllib import quote_plus
    
    print(quote_plus('MY USERNAME'))
    print(quote_plus('MY PASSWORD'))
    

    获取输出并将其放入 Atlas 给您的连接字符串中,例如如果您的用户名是 jesse@example.com 并且您的密码是“foo:bar”,请将其放在字符串的第一部分,然后从 Atlas 控制面板为您的帐户获取字符串的其余部分:

    mongodb://jesse%40example.com:foo%3Abar/@cluster0-shard-00-00-abc.mongodb.net:27017,cluster0-shard-00-01-abc.mongodb.net:27017,cluster0-shard-00-02-abc.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin
    

    注意“jesse@example.com”如何变成“jesse%40example.com”,“foo:bar”变成“foo%3Abar”。

    【讨论】:

    • 工作感谢。 Python 3 导入from urllib.parse import quote_plus。是否可以将它添加到需要引用具有特殊字符的用户名/密码才能工作的文档中?
    • 这在此处记录:api.mongodb.com/python/current/examples/authentication.html ...但我还要求 Atlas 团队将该信息放入 Atlas 仪表板中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    相关资源
    最近更新 更多