循环 Pymongo 游标会在一些迭代后返回 bson.errors.InvalidBSON 错误



我正在尝试使用 pymongo 进行简单的查询并循环结果。

这是我正在使用的代码:

data = []
tam = db.my_collection.find({'timestamp': {'$gte': start, '$lte':end}}).count()
for i,d in enumerate(table.find({'timestamp': {'$gte': start, '$lte':end}}):
    print('%s of %s' % (i,tam))
    data.append(d)

开始和结束变量是日期时间 Python 对象。一切正常,直到我得到以下输出:

2987 of 12848
2988 of 12848
2989 of 12848
2990 of 12848
2991 of 12848
2992 of 12848
Traceback (most recent call last):
  File "db_extractionextract_data.py", line 68, in <module>
    data = extract_data(yesterday,days = 1)
  File "db_extractionextract_data.py", line 24, in extract_data
    for i,d in enumerate(table.find({'timestamp': {'$gte': start, '$lte':end}}).limit(100000)):
  File "venvlibsite-packagespymongocursor.py", line 1169, in next
    if len(self.__data) or self._refresh():
  File "venvlibsite-packagespymongocursor.py", line 1106, in _refresh
    self.__send_message(g)
  File "venvlibsite-packagespymongocursor.py", line 971, in __send_message
    codec_options=self.__codec_options)
  File "venvlibsite-packagespymongocursor.py", line 1055, in _unpack_response
    return response.unpack_response(cursor_id, codec_options)
  File "venvlibsite-packagespymongomessage.py", line 945, in unpack_response
    return bson.decode_all(self.documents, codec_options)
bson.errors.InvalidBSON

我尝试的第一件事是更改查询的范围以检查它是否与数据相关,而不是。另一个范围停止在 1615 的 6360 和相同的错误。

我也尝试了list(table.find({'timestamp': {'$gte': start, '$lte':end}})和相同的错误。

另一个可能相关的信息是,第一次查询非常快。它会在返回错误之前冻结在最后一个数字上一段时间。

所以我需要一些帮助。我在这里达到极限了吗?或者有什么线索吗?

这可能与 2013 年的问题有关,但作者说他没有得到错误输出。

谢谢!

编辑:

首先感谢大家的时间和建议。不幸的是,我已经测试了所有设备,但在同一位置遇到了相同的错误。我已经使用 mongo shell 打印了有问题的文件,它与所有其他文件几乎相同。 我更改了查询的范围,并尝试在其他日子上继续。所有日子都有同样的问题,直到我发现一个随机运行给了我一个内存错误。

1737 of 8011
1738 of 8011
1739 of 8011
1740 of 8011
1741 of 8011
Traceback (most recent call last):
  File "db_extractionpymongo_test.py", line 14, in <module>
    for post in all_posts:
  File "python_modulesvenvlibsite-packagespymongocursor.py", line 1189, in next
    if len(self.__data) or self._refresh():
  File "python_modulesvenvlibsite-packagespymongocursor.py", line 1126, in _refresh
    self.__send_message(g)
  File "python_modulesvenvlibsite-packagespymongocursor.py", line 931, in __send_message
    operation, exhaust=self.__exhaust, address=self.__address)
  File "python_modulesvenvlibsite-packagespymongomongo_client.py", line 1145, in _send_message_with_response
    exhaust)
  File "python_modulesvenvlibsite-packagespymongomongo_client.py", line 1156, in _reset_on_error
    return func(*args, **kwargs)
  File "python_modulesvenvlibsite-packagespymongoserver.py", line 106, in send_message_with_response
    reply = sock_info.receive_message(request_id)
  File "python_modulesvenvlibsite-packagespymongopool.py", line 612, in receive_message
    self._raise_connection_failure(error)
  File "python_modulesvenvlibsite-packagespymongopool.py", line 745, in _raise_connection_failure
    raise error
  File "python_modulesvenvlibsite-packagespymongopool.py", line 610, in receive_message
    self.max_message_size)
  File "python_modulesvenvlibsite-packagespymongonetwork.py", line 191, in receive_message
    data = _receive_data_on_socket(sock, length - 16)
  File "python_modulesvenvlibsite-packagespymongonetwork.py", line 227, in _receive_data_on_socket
    buf = bytearray(length)
MemoryError

这是间歇性的。我再次运行而没有更改任何内容,并得到了旧的无效BSON错误,然后再次运行并出现内存错误。

我启动了任务管理器并再次运行,内存确实快速增长到95%的使用率并挂起在那里。查询应该在 1GB RAM 机器中检索 8GB 的数据,所以......我不知道这是否应该发生。无论如何,使用 pymongo 从 mongoDB 检索数据并写入文件而不将所有内容放入内存的代码建议可能会完成这项工作。好处是,如果有人可以解释为什么在我的情况下我得到一个无效的 BSON 而不是 MemoryError(对于绝大多数运行(。

谢谢

你的代码在我的电脑上运行良好。由于它适用于您的前 2992 条记录,我认为文档可能存在一些不一致之处。集合中的每个文档是否都遵循相同的架构和格式?你的皮蒙戈更新了吗?

如果您想遍历每条记录,这是我的建议:

data = []
all_posts = db.my_collection.find({'timestamp': {'$gte': start, '$lte':end}})
tam = all_posts.count()
i = 0
for post in all_posts:
    i += 1
    print('%s of %s' % (i,tam))
    data.append(post)

问候

我自己也遇到了同样的问题,它最终与文档本身无关,而是与程序在大型查询期间占用的内存量有关。

在我们的特定情况下,当在单独的脚本中运行为我们提供此确切错误的损坏查询时,该错误没有发生。最终我们发现我们使用的是 uwsgi 配置设置:

limit-as = 512

当地址空间达到 512M 时,这将立即终止我们的进程,导致 InvalidBSON 错误或 MemoryError 互换,似乎是随机的。

我们通过更改限制-as-设置为重新加载-as来解决此问题:

reload-on-as = 512

最终,我们最终决定将这样的大型查询分解为更小的部分,并按顺序执行它们,而不是一次执行,但我们至少确定这是一个外部原因,而不是pymongo驱动程序本身的问题。

它是否与数据库中的特定文档有关?您是否检查了可能导致错误的文档(例如,上述查询的第 2992 个结果,从 0 开始(?

您也可以直接对数据库执行一些查询(例如,通过 mongo shell(,而无需使用 pymongo 查看是否返回预期结果。例如,您可以尝试db.my_collection.find({...}).skip(2992)以查看结果。您还可以使用cursor.forEach()打印所有检索到的文档。

最新更新