Unable to convert decimal to Decimal128 in python

Question:

My Django project (python==3.10.3, Django==4.0.4) is accessing an MSSQL server via pymssql (pymssql==2.2.5), scraping what I need, and getting a list of dicts.
I then save to MongoDB (pymongo==4.2.0) but there are decimal values that need to be Decimal128. I found Pymongo: Cannot encode object of type decimal.Decimal? which has a similar goal as mine. So I adapted to handle the list of dict like this:

def convert_decimal_iterdict(list_of_dict):
    if list_of_dict is None:
        return None

    for i in list_of_dict:
        for k, v in i.items():
            if isinstance(v, dict):
                convert_decimal_iterdict(v)
            elif isinstance(v, list):
                for l in v:
                    convert_decimal_iterdict(l)
            elif isinstance(v, Decimal):
                list_of_dict[k] = Decimal128(str(v))

    return list_of_dict

It errors with

   list_of_dict[k] = Decimal128(str(v))
TypeError: list indices must be integers or slices, not str

So I attempted to use Decimal, float, or int…

                list_of_dict[k] = Decimal128(Decimal(v))

but get

#Decimal
   raise TypeError("Cannot convert %r to Decimal128" % (value,))
TypeError: Cannot convert 1 to Decimal128

#float
    raise TypeError("Cannot convert %r to Decimal128" % (value,))
TypeError: Cannot convert 1.0 to Decimal128

#int
    raise TypeError("Cannot convert %r to Decimal128" % (value,))
TypeError: Cannot convert 1 to Decimal128

removing altogether

                list_of_dict[k] = Decimal128(v)

just gives the original ‘not str’ TypeError:

I’m sure it’s something easy that i’m just not seeing. I know you can’t

Asked By: Bammer

||

Answers:

Let’s take a closer look at the line at which an error is being raised:

                list_of_dict[k] = Decimal128(str(v))

list_of_dict is a list, k is a key from one of the dicts. From your error message, k is evidently a string. If you’re indexing a list, you should be using list indexes, not dict keys.

What you seem to want to do is to convert a single decimal value in one of the dicts to Decimal128. The current dict you are iterating through is in the variable i, so try changing the line above to this:

                i[k] = Decimal128(str(v))

(You might also want to consider improving the name of the variable i, both to make it more descriptive, and also because i, j, k etc. are often used as loop counter variables containing integer values.)

Finally, I must state that this code hasn’t been tested. I don’t have a copy of MongoDB installed.

Answered By: Luke Woodward
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.