首页 > 解决方案 > 如何将 python dict 转换为 DictRow 对象

问题描述

嗨,我正在使用 pytest 编写单元测试。但我无法模拟几个数据库函数。我们使用 psycopg2 进行数据库连接和执行。从 psycopg2 返回的查询响应属于 DictRow 类型,可以通过键或索引访问。前任:

response = ['prajwal', '23', 'engineer'] #Response of a query "select name, age , job from users"

>>>response[0]
   'prajwal'
    
>>>response['name']
   'prajwal'

我想知道有什么方法可以将 dict/list 转换为上述类型。

标签: python-3.xunit-testingpytestpsycopg2

解决方案


查看 的来源psycopg2,创建一个DictRow需要传入一个DictCursor对象。然而,它使用的唯一东西DictCursor似乎是一个indexdescription属性。

# found in lib\site-packages\psycopg2.extras.py
class DictRow(list):
    """A row object that allow by-column-name access to data."""

    __slots__ = ('_index',)

    def __init__(self, cursor):
        self._index = cursor.index
        self[:] = [None] * len(cursor.description)

索引看起来像一个dict将键映射到索引的索引。例如response['name'] = 0 ,描述看起来像您dict要转换的。

如果你觉得 hacky,你可以利用鸭子打字,cursor当你只是满足要求时假装你通过了。

唯一需要注意的是,在我们实例化 之后DictRow,我们需要填充它。我们的假cursor黑客会处理剩下的事情。

from psycopg2.extras import DictRow

class DictRowHack:
    def __init__(self, my_dict):
        # we need to set these 2 attributes so that
        # it auto populates our indexes
        self.index = {key: i for i, key in enumerate(my_dict)}
        self.description = my_dict

def dictrow_from_dict(my_dict):
    # this is just a little helper function
    # so you don't always need to go through
    # the steps to recreate a DictRow
    fake_cursor = DictRowHack(my_dict)

    my_dictrow = DictRow(fake_cursor)

    for k, v in my_dict.items():
        my_dictrow[k] = v
    
    return my_dictrow

response = {'name': 'prajwal', 'age': '23', 'job': 'engineer'}

my_dictrow = dictrow_from_dict(response)

print(my_dictrow[1])
print(my_dictrow['name'])
print(type(my_dictrow))

推荐阅读