【问题标题】:Making a Dictionary List with cx_Oracle使用 cx_Oracle 制作字典列表
【发布时间】:2012-05-14 09:55:09
【问题描述】:

我一直在使用以下函数来制作一种“更易读”(据说)格式来从 Oracle 获取数据。这是函数:

def rows_to_dict_list(cursor):
    """ 
    Create a list, each item contains a dictionary outlined like so:
    { "col1_name" : col1_data }
    Each item in the list is technically one row of data with named columns,
    represented as a dictionary object
    For example:
    list = [
        {"col1":1234567, "col2":1234, "col3":123456, "col4":BLAH},
        {"col1":7654321, "col2":1234, "col3":123456, "col4":BLAH}
    ]
    """

    # Get all the column names of the query.
    # Each column name corresponds to the row index
    # 
    # cursor.description returns a list of tuples, 
    # with the 0th item in the tuple being the actual column name.
    # everything after i[0] is just misc Oracle info (e.g. datatype, size)
    columns = [i[0] for i in cursor.description]

    new_list = []
    for row in cursor:
        row_dict = dict()
        for col in columns:
            # Create a new dictionary with field names as the key, 
            # row data as the value.
            #
            # Then add this dictionary to the new_list
            row_dict[col] = row[columns.index(col)]

        new_list.append(row_dict)
    return new_list

然后我会像这样使用函数:

sql = "Some kind of SQL statement"
curs.execute(sql)
data = rows_to_dict_list(curs)
#
for row in data:
    item1 = row["col1"]
    item2 = row["col2"]
    # Do stuff with item1, item2, etc...
    # You don't necessarily have to assign them to variables,
    # but you get the idea.

虽然这似乎在不同程度的压力下表现得相当好,但我想知道是否有更有效或“pythonic”的方式来做到这一点。

【问题讨论】:

    标签: python oracle cx-oracle


    【解决方案1】:

    还有其他改进,但这真的让我大吃一惊:

        for col in columns:
            # Create a new dictionary with field names as the key, 
            # row data as the value.
            #
            # Then add this dictionary to the new_list
            row_dict[col] = row[columns.index(col)]
    

    除了效率低下之外,在这种情况下使用index 还容易出错,至少在同一项目可能在列表中出现两次的情况下。请改用enumerate

        for i, col in enumerate(columns):
            # Create a new dictionary with field names as the key, 
            # row data as the value.
            #
            # Then add this dictionary to the new_list
            row_dict[col] = row[i]
    

    但那只是小土豆,真的。这是这个函数的一个更紧凑的版本:

    def rows_to_dict_list(cursor):
        columns = [i[0] for i in cursor.description]
        return [dict(zip(columns, row)) for row in cursor]
    

    让我知道这是否有效。

    【讨论】:

    • 如果需要对每一行的元素进行一些后期处理怎么办。那么这将不起作用 -> [dict(zip(columns, row)) for row in cursor]
    • @ramu,这对我来说听起来像是一个新问题。如果有人还没有在这里问过,也许你应该问。
    • 传奇!谢谢
    【解决方案2】:

    您不应该将 dict 用于大型结果集,因为内存使用量会很大。我经常使用 cx_Oracle,但没有一个很好的字典游标困扰着我,无法为它编写一个模块。我还必须将 Python 连接到许多不同的数据库,所以我使用的方式可以与任何 DB API 2 连接器一起使用。

    它在 PyPi 上 DBMS - DataBases Made Simpler

    >>> import dbms
    >>> db = dbms.OraConnect('myUser', 'myPass', 'myInstance')
    >>> cur = db.cursor()
    >>> cur.execute('SELECT * FROM people WHERE id = :id', {'id': 1123})
    >>> row = cur.fetchone()
    >>> row['last_name']
    Bailey
    >>> row.last_name
    Bailey
    >>> row[3]
    Bailey
    >>> row[0:4]
    [1123, 'Scott', 'R', 'Bailey']
    

    【讨论】:

      【解决方案3】:

      为了避免将所有内容预先转储到列表中而导致内存使用的干净方法,您可以将光标包装在生成器函数中:

      def rows_as_dicts(cursor):
          """ returns cx_Oracle rows as dicts """
          colnames = [i[0] for i in cursor.description]
          for row in cursor:
              yield dict(zip(colnames, row))
      

      然后使用如下 - 来自游标的行在迭代时被转换为字典:

      for row in rows_as_dicts(cursor):
          item1 = row["col1"]
          item2 = row["col2"]
      

      【讨论】:

      • 这对于大型结果集可能很好,但我发现它的性能不如@senderle 对于相对较小的结果集的答案。
      • @bspkrs 谢谢 - 我可以看到。你有任何关于你看到的实际性能差异的数字吗?
      • Python 还允许您内联生成器:for row in (i[0] for i in cursor.description):。不需要单独的函数。
      • @jpmc26 这是一个很好的建议——我倾向于忘记它!
      【解决方案4】:

      假设光标“Cursor”已经被定义并且迫不及待:

      byCol = {cl:i for i,(cl,type, a, b, c,d,e) in enumerate(Cursor.description)}

      那么你就可以走了:

      for row in Cursor: column_of_interest = row[byCol["COLUMN_NAME_OF_INTEREST"]]

      不像系统自己处理那样干净流畅,但也不可怕。

      【讨论】:

        【解决方案5】:

        创建一个字典

        cols=dict()
        for col, desc in enumerate(cur.description):
            cols[desc[0]] = col
        

        访问:

        for result in cur
            print (result[cols['COL_NAME']])
        

        【讨论】:

          【解决方案6】:

          我有一个更好的:

          import cx_Oracle
          
          def makedict(cursor):
          """Convert cx_oracle query result to be a dictionary   
          """
          cols = [d[0] for d in cursor.description]
          
          def createrow(*args):
              return dict(zip(cols, args))
          
          return createrow
          
          db = cx_Oracle.connect('user', 'pw', 'host')
          cursor = db.cursor()
          rs = cursor.execute('SELECT * FROM Tablename')
          cursor.rowfactory = makedict(cursor)
          

          【讨论】:

            猜你喜欢
            • 2020-03-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-23
            • 2019-10-17
            相关资源
            最近更新 更多