Text formatting error: '=' alignment not allowed in string format specifier

Question:

What does '=' alignment mean in the following error message, and why does this code cause it?

>>> "{num:03}".format(num="1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: '=' alignment not allowed in string format specifier

The code has a subtle problem: the input value "1" is text, not a number. But the error message doesn’t appear to have anything to do with that.

Nothing in the error message indicates why “’=’ alignment” is relevant,
and it does not appear in the code. So what is the significance of emitting that error message?

Asked By: bignose

||

Answers:

This format would be acceptable

"{num}:03".format(num="1")

but the way you have the placeholder specified {num:03} is not. That is an interesting ValueError though, if you remove the : the interesting error is replaced by a standard KeyError.

Answered By: pholtz

str.__format__ doesn’t know what to do with your 03 part. That only works with numbers:

>>> "{num:03}".format(num=1)
'001'

If you actually want to zero-pad a string, you can use rjust:

>>> "1".rjust(3, "0")
'001'
Answered By: L3viathan

Python 3.10 and later

This issue is corrected in Python 3.10 and later:

In string formatting, preceding the width field by ‘0’ no longer affects the default alignment for strings.

The example code no longer raises an error; instead, it gives the result '100' because the default align for non-numeric types is <.

Python earlier than 3.10

The error message occurs because '=' alignment has been implied by the format specifier.

The str.format format spec mini-language parser has decided on the
alignment specifier “=” because:

Preceding the width field by a zero (‘0’) character enables
sign-aware zero-padding for numeric types. This is equivalent to a
fill character of ‘0’ with an alignment type of ‘=’.

So by specifying 0N as the “zero-padding to N width”, you have implied both “the input is a numeric type”, and “the zeros should go between the sign and the digits”. That latter implication is what is meant by '=' alignment.

Since the value "1" is not numeric, the “=”-alignment handling code raises that exception. The message is written expecting you know what it’s talking about because you requested (by implication) the “=” alignment.

Yes, I think that error message needs to be improved. I’ve raised an issue for that. Thanks to Serhiy Storchaka for fixing this issue! Python 3.10 includes this change.

Answered By: bignose

You are trying to insert ‘string->”1″ where a float->3.44 is required. Remove the quotes “1”, i.e. num=1, and it will work

Answered By: diahron

A workaround is to use '>' (right justify) padding, which is with the syntax:

[[fill]align][width]

with align being >, fill being 0 and width being 3.

>>> "{num:0>3}".format(num="1")
'001'

The problem was that there is a different 0 in the format specification:

format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
#                                          ^^^ This one

That zero just makes fill default to 0 and align to =.

= alignment is specified as:

Forces the padding to be placed after the sign (if any) but before the digits. This is used for printing fields in the form ‘+000000120’. This alignment option is only valid for numeric types. It becomes the default when ‘0’ immediately precedes the field width.

Source (Python 3 docs)

This expects the argument to be an int, as strings don’t have signs. So we just manually set it to the normal default of > (right justify).

Also note that 0 just specifies the default values for fill and align. You can change both or just the align.

>>> # fill defaults to '0', align is '>', `0` is set, width is `3`
>>> "{num:>03}".format(num=-1)
'0-1'
>>> # fill is `x`, align is '>', `0` is set (but does nothing), width is `"3"`
>>> "{num:x>03}".format(num=-1)
'x-1'
>>> # fill is `x`, align is '>', `0` is set (but does nothing), width is `"03"` (3)
>>> "{num:x>003}".format(num=-1)
'x-1'
Answered By: Artyer

In my case, I was trying to zero-pad a string instead of a number.

The solution was simply to convert the text to a number before applying the padding:

num_as_text = '23'
num_as_num = int(num_as_text)
padded_text = f'{num_as_num:03}'
Answered By: Eric McLachlan

Changed in version 3.10: Preceding the width field by ‘0’ no longer affects the default
alignment for strings.

Thanks to Serhiy Storchaka for fixing it.

The OP’s code sample runs fine in Python 3.10+. However note that it returns 100 because the default align for non-numeric types is <.

For older Python versions manually add the left alignment character: "{num:<03}".format(num="1")

Answered By: AXO

Just for others who google searched and found this Q&A.

This error:

    out_name = track_name_fmt.format(track, song)
ValueError: '=' alignment not allowed in string format specifier

Was fixed by using:

out_name = track_name_fmt.format(int(track), song)

Forcing track to integer solved the problem.

Answered By: WinEunuuchs2Unix
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.