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

时间:2018-08-07 20:21:53

标签: python mongodb pymongo

我正在尝试使用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_extraction\extract_data.py", line 68, in <module>
    data = extract_data(yesterday,days = 1)
  File "db_extraction\extract_data.py", line 24, in extract_data
    for i,d in enumerate(table.find({'timestamp': {'$gte': start, '$lte':end}}).limit(100000)):
  File "\venv\lib\site-packages\pymongo\cursor.py", line 1169, in next
    if len(self.__data) or self._refresh():
  File "\venv\lib\site-packages\pymongo\cursor.py", line 1106, in _refresh
    self.__send_message(g)
  File "\venv\lib\site-packages\pymongo\cursor.py", line 971, in __send_message
    codec_options=self.__codec_options)
  File "\venv\lib\site-packages\pymongo\cursor.py", line 1055, in _unpack_response
    return response.unpack_response(cursor_id, codec_options)
  File "\venv\lib\site-packages\pymongo\message.py", line 945, in unpack_response
    return bson.decode_all(self.documents, codec_options)
bson.errors.InvalidBSON

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

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

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

所以我需要一些帮助。我在这里达到极限吗?或有关发生什么情况的任何线索?

这可能与this 2013 question有关,但是作者说他没有收到错误输出。

谢谢!

编辑:

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

1737 of 8011
1738 of 8011
1739 of 8011
1740 of 8011
1741 of 8011
Traceback (most recent call last):
  File "db_extraction\pymongo_test.py", line 14, in <module>
    for post in all_posts:
  File "\python_modules\venv\lib\site-packages\pymongo\cursor.py", line 1189, in next
    if len(self.__data) or self._refresh():
  File "\python_modules\venv\lib\site-packages\pymongo\cursor.py", line 1126, in _refresh
    self.__send_message(g)
  File "\python_modules\venv\lib\site-packages\pymongo\cursor.py", line 931, in __send_message
    operation, exhaust=self.__exhaust, address=self.__address)
  File "\python_modules\venv\lib\site-packages\pymongo\mongo_client.py", line 1145, in _send_message_with_response
    exhaust)
  File "\python_modules\venv\lib\site-packages\pymongo\mongo_client.py", line 1156, in _reset_on_error
    return func(*args, **kwargs)
  File "\python_modules\venv\lib\site-packages\pymongo\server.py", line 106, in send_message_with_response
    reply = sock_info.receive_message(request_id)
  File "\python_modules\venv\lib\site-packages\pymongo\pool.py", line 612, in receive_message
    self._raise_connection_failure(error)
  File "\python_modules\venv\lib\site-packages\pymongo\pool.py", line 745, in _raise_connection_failure
    raise error
  File "\python_modules\venv\lib\site-packages\pymongo\pool.py", line 610, in receive_message
    self.max_message_size)
  File "\python_modules\venv\lib\site-packages\pymongo\network.py", line 191, in receive_message
    data = _receive_data_on_socket(sock, length - 16)
  File "\python_modules\venv\lib\site-packages\pymongo\network.py", line 227, in _receive_data_on_socket
    buf = bytearray(length)
MemoryError

这是间歇性的。我再次运行,没有进行任何更改,并得到了旧的invalidBSON错误,然后再次运行,并遇到了内存错误。

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

谢谢

3 个答案:

答案 0 :(得分:1)

您的代码在我的计算机上运行良好。由于它适用于您的前2992条记录,因此我认为这些文档可能存在一些不一致之处。集合中的每个文档都遵循相同的架构和格式吗?并且您的pymongo是否已更新?

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

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)

此致

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

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

limit-as = 512

当地址空间达到512M时,这会立即终止我们的进程,从而导致InvalidBSON错误或MemoryError交替出现,这似乎是随机的。

我们通过更改limit-as设置为reload-on-as来解决此问题:

reload-on-as = 512

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