Python 2.7 Azure存储表[Python]-批处理未失败

Python 2.7 Azure存储表[Python]-批处理未失败,python-2.7,azure,transactions,etag,azure-table-storage,Python 2.7,Azure,Transactions,Etag,Azure Table Storage,我目前正在开发一个Python(2.7)应用程序,它通过Azure Python包使用Azure表存储服务。据我从Azure的REST API中了解到的,批处理操作创建原子事务。因此,如果其中一个操作失败,则整个批处理失败,并且不执行任何操作 我遇到的问题如下: 下面的方法通过“rows”参数接收DICT列表。一些具有ETag集(从以前的查询中提供) 如果设置了ETag,请尝试合并操作。否则,请尝试插入操作。由于有多个进程可能修改同一实体,因此需要通过merge_entity函数的“if_mat

我目前正在开发一个Python(2.7)应用程序,它通过Azure Python包使用Azure表存储服务。据我从Azure的REST API中了解到的,批处理操作创建原子事务。因此,如果其中一个操作失败,则整个批处理失败,并且不执行任何操作

我遇到的问题如下: 下面的方法通过“rows”参数接收DICT列表。一些具有ETag集(从以前的查询中提供)

如果设置了ETag,请尝试合并操作。否则,请尝试插入操作。由于有多个进程可能修改同一实体,因此需要通过merge_entity函数的“if_match”参数来解决并发问题。如果合并/插入操作是单独的操作(不包括在批处理中),系统将按预期工作,如果ETag不匹配,将引发异常。 不幸的是,如果它们被包装在“begin\u batch”/“commit\u batch”调用中,则不会发生这种情况。即使ETag不匹配,也会合并实体(错误)

我在下面提供了所使用的代码和测试用例。还进行了多次手动测试,得出了相同的结论

我不确定如何处理这个问题。我是做错了什么,还是Python包有问题

使用的代码如下所示:

def persist_entities(self, rows):
    success = True
    self._service.begin_batch()        #If commented, works as expected (fails)
    for row in rows:
        print row
        etag = row.pop("ETag")
        if not etag:
            self._service.insert_entity(self._name,
                                        entity=row)
        else:
            print "Merging " + etag
            self._service.merge_entity(self._name,
                                       row["PartitionKey"],
                                       row["RowKey"],
                                       row, if_match=etag)
    try:            #Also tried with the try at the begining of the code
        self._service.commit_batch()       #If commented, works as expected (fails)
    except WindowsAzureError:
        print "Failed to merge"
        self._service.cancel_batch()
        success = False
    return success
所使用的测试用例:

def test_fail_update(self):
        service = self._conn.get_service()
        partition, new_rows = self._generate_data()   #Partition key and list of dicts
        success = self._wrapper.persist_entities(new_rows)   #Inserts fresh new entity
        ok_(success)                                           #Insert succeeds
        rows = self._wrapper.get_entities_by_row(partition) #Retreives inserted data for ETag
        eq_(len(rows), 1)
        for index in rows:
            row = rows[index]
            data = new_rows[0]
            data["Count"] = 155                       #Same data, different value
            data["ETag"] = "random_etag"              #Change ETag to a random string
            val = self._wrapper.persist_entities([data])              #Try to merge
            ok_(not val)            #val = True for merge success, False for merge fail.
            #It's always True when operations in batch. False if operations out of batch 
            rows1 = self._wrapper.get_entities_by_row(partition)
            eq_(len(rows1), 1)
            eq_(rows1[index].Count, 123)
            break

    def _generate_data(self):
        date = datetime.now().isoformat()
        partition = "{0}_{1}_{2}".format("1",
                                         Stats.RESOLUTION_DAY, date)
        data = {
            "PartitionKey": partition,
            "RowKey": "viewitem",
            "Count": 123,
            "ETag": None
        }
        return partition, [data]
这是SDK(v0.8及更早版本)中的一个bug。我已经创建了一个问题并签入了修复程序。这将是下一版本的一部分。您可以从git repo进行pip安装以测试修复程序。
Azure Table Storage在预览版中有一个新的python库,可通过pip进行安装。要安装,请使用以下pip命令

pip install azure-data-tables
在最新的库中,执行批处理的方式和批处理的工作方式存在一些差异

  • 批处理操作只能在包含相同分区键的实体上提交
  • 批处理操作不能在同一行键上包含多个操作
  • 仅当整个批处理成功时才会提交批处理,如果
    发送批处理
    引发错误,则不会进行更新
  • 说明了这一点后,创建和更新操作与非批处理创建和更新操作的工作方式相同。例如:

    from azure.data.tables import TableClient, UpdateMode
    table_client = TableClient.from_connection_string(conn_str, table_name="myTable")
    
    batch = table_client.create_batch()
    batch.create_entity(entity1)
    batch.update_entity(entity2, etag=etag, match_condition=UpdateMode.MERGE)
    batch.delete_entity(entity['PartitionKey'], entity['RowKey'])
    
    try:
        table_client.send_batch(batch)
    except BatchErrorException as e:
        print("There was an error with the batch")
        print(e)
    
    有关新库的更多示例,请查看存储库上的页面


    (仅供参考,我是Azure SDK for Python团队的Microsoft员工)

    感谢您的回答和暗示。我期待着你的下一个版本。我还将尽快测试修复程序并向您提供反馈。看来
    commit\u batch
    已重命名为
    send\u batch
    @MaxLap谢谢您的关注,我已更新了我的回复。