关于mongodb更新操作中safe=True参数的问题

4 投票
2 回答
3900 浏览
提问于 2025-04-16 23:47

我正在使用 pymongo 这个 Python 模块来操作 MongoDB 数据库。在我的代码中,有一个函数,当调用它时,会更新集合中的记录,代码如下:

for record in coll.find(<some query here>):
   #Code here
   #...
   #...
   coll.update({ '_id' : record['_id'] },record)

现在,如果我把代码修改成这样:

for record in coll.find(<some query here>):
   try:
       #Code here
       #...
       #...
       coll.update({ '_id' : record['_id'] },record,safe=True)
   except:
        #Handle exception here

这样做是否意味着如果更新失败,就会抛出一个异常,还是说不会抛出异常,更新会跳过这个记录,从而导致问题呢?

请帮帮我,谢谢!

2 个回答

3

tryexcept 这两个东西不会自己制造错误,它们只是用来处理已经出现的错误。

如果 update 在失败时抛出了一个错误,except 就会处理这个错误,然后循环会继续进行(除非你在 except 里使用了 raise 来重新抛出错误)。

如果 update 在失败时没有抛出错误,而是返回了 None(或者类似的东西),而你又希望它抛出一个错误,你可以使用:

if coll.update(...) is None: # or whatever it returns on failure
    raise ValueError # or your custom Exception subclass

注意,你应该总是指定你想要捕捉的错误类型,并且只把你想要捕捉错误的代码行放在 try 里,这样就不会把其他错误隐藏起来:

for record in coll.find(<some query here>):
   #Code here
   #...
   #...
   try:
       coll.update({ '_id' : record['_id'] },record,safe=True)
   except SpecificException:
        #Handle exception here
   except OtherSpecificException:
        #Handle exception here
   else:
        #extra stuff to do if there was no exception

可以查看 try 语句内置异常错误和异常

3

使用 safe=True 这个设置时,如果数据库出现错误,就会抛出一些异常,比如 pymongo.errors.OperationFailure 或它的子类(想了解更多可以查看 pymongo 的文档)。举个例子,我这里制造了一个唯一索引的重复键错误:

>>> db.bar.insert({'a': 1, 'b': 1})
ObjectId('4e4bc586c67f060b25000000')
>>> db.bar.ensure_index('a', unique=True)
u'a_1'
>>> db.bar.insert({'a': 2, 'b': 1}, safe=True)
ObjectId('4e4bc71fc67f060b25000003')
>>> db.bar.update({'a': 2}, {'a': 1}, safe=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 368, in update
    spec, document, safe, kwargs), safe)
  File "/Library/Python/2.7/site-packages/pymongo/connection.py", line 770, in _send_message
    return self.__check_response_to_last_error(response)
  File "/Library/Python/2.7/site-packages/pymongo/connection.py", line 718, in __check_response_to_last_error
    raise DuplicateKeyError(error["err"])
pymongo.errors.DuplicateKeyError: E11000 duplicate key error index: test.bar.$a_1  dup key: { : 1 }

(注意,DuplicateKeyErrorOperationFailure 的一个子类,所以 except OperationFailure: ... 这样的写法会按预期工作。)

除了 update() 方法,save()insert()remove() 这些方法也都可以接受 safe 这个参数。你还可以在 Connection 级别设置 safe,这样就不需要在每次修改数据库时都加上这个参数了。

撰写回答