[Django]-Unknown format code 'f' for object of type 'unicode'

22👍

In your case num is a unicode string, which does not support the f format modifier:

>>> '{0:.2f}'.format(u"5.0")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'f' for object of type 'unicode'

You can fix the error making the conversion to float yourself:

>>> '{0:.2f}'.format(float(u"5.0"))
'5.00'

As pointed out by mgilson when you do '{0:.2f}'.format(num), the format method of the strings calls num.__format__(".2f"). This results in an error for str or unicode, because they don’t know how to handle this format specifier. Note that the meaning of f is left as an implementation for the object. For numeric types it means to convert the number to a floating point string representation, but other objects may have different conventions.

If you used the % formatting operator the behaviour is different, because in that case %f calls __float__ directly to obtain a floating point representation of the object.
Which means that when using %-style formatting f does have a specific meaning, which is to convert to a floating point string representation.

5👍

what .format() do

str.format method calls __format__() method of related type. That means

<type>.__format__(<value>, <spec>)

above method accepts the same type argument as first value, and accepts a suitable spec type
as second one. Like,

str.__format__('1', 's')
int.__format__(1, 'f')
float.__format__(1.00, 'f')

str.__format__ accepts any type that is derived from str type, like str or unicode. Spec value must be a valid formatter that is usable of that type. Following will raise an error

str.__format__('1', 'f')
ValueError: Unknown format code 'f' for object of type 'str'

since floating point formatting is not a suitable format type fot string. Likewise following will raise an error too

float.__format__(1.00, 's')
ValueError: Unknown format code 's' for object of type 'float'

since float is a numeric type and can not formatted as a string. But following are all valid:

float.__format__(1.00, 'g')
float.__format__(1.00, 'f')

similarly following will raise an exception

float.__format__(1.00, 'd')
ValueError: Unknown format code 'd' for object of type 'float'

since formatting a float point to a decimal value will cause precision values to be lost. But formatting an int to float will not cause a such thing, so it is a valid conversion:

int.__format__(1, 'f')

So .format() is limeted to specs that is available to the related formatting type. You must parse your value as @Bakuriu defined:

'{0:.2f}'.format(float(u"5.0"))
👤Mp0int

1👍

The scenario where you are re-formatting a string (unicode or otherwise) as a float string is not very safe. You should first convert the string to a numeric representation and only if that succeeds should you format it as a string again. You are not in control of the data that comes into your program so you should be sure to validate it coming in.

If you choose to leave it as a string you can use this:

return u"{:.2f}".format(num) if num.isnumeric() else u"{}".format(num)

If you have already converted the string into a numeric format, you can adjust your formatter like this:

return u"{:.2f}".format(num) if isinstance(num, NumberTypes) else u"{}".format(num)

0👍

I’ve faced a similar problem as the OP, when num was a numerical answer returned by one of my libraries, whose implementation detais got forgotten:

>>> num
-4132.56528214700
>>> u'{0:.4g}'.format(num)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'g' for object of type 'unicode'

I was really puzzled because num behaved like a float but after testing @Bakuriu ‘s solution, I’ve found out it wasn’t a float:

>>> type(num)
<class 'sympy.core.numbers.Float'>

So @Bakuriu ‘s solution was right on target for my case:

>>> u'{0:.4g}'.format(float(num))
u'-4133'

Therefore, the error can be due to types that display/calculate like but aren’t really floats.

👤cnaak

Leave a comment