文本格式错误:在字符串格式说明符中不允许'='对齐。

55

以下错误信息中的'=' alignment是什么意思,为什么这段代码会导致此错误?

>>> "{num:03}".format(num="1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: '=' alignment not allowed in string format specifier
代码存在一个微妙的问题:输入值"1"是文本,而不是数字。但错误消息似乎与此无关。
错误消息中没有任何提示表明为什么“'=' alignment”相关,并且它在代码中也未出现。那么发出该错误消息的意义是什么?
8个回答

69

Python 3.10及以上版本

这个问题在Python 3.10及以上版本中已经得到修正:

在字符串格式化中,使用'0'作为宽度字段的前缀不再影响字符串的默认对齐方式。

示例代码不再引发错误;相反,它会给出结果'100',因为非数字类型的默认align<

Python 3.10之前的版本

错误消息出现是因为格式说明符隐含了'='对齐

str.format格式规范微语言解析器决定采用“=”对齐说明符,因为:

在宽度字段前加零('0')字符可启用数值类型的符号感知零填充。这相当于一个填充字符为'0',对齐类型为'='的说明符。

因此,通过将0N指定为“零填充到N宽度”,您已经暗示了“输入是数字类型”和“零应该放在符号和数字之间”。 后一种含义就是所谓的'='对齐

由于值"1"不是数字,因此“=”对齐处理代码会引发异常。 该消息的编写者期望您知道它在说什么,因为您(通过暗示)请求了“=”对齐。

是的,我认为需要改进这个错误消息。 我已经提出了这个问题 感谢Serhiy Storchaka 修复了这个问题Python 3.10包括了这个更改


40
一个解决方法是使用'>'(右对齐)填充,语法如下:
[[fill]align][width]

使用 > 对齐,填充为 0,宽度为 3

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

问题在于格式规范中有一个不同的0
format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
#                                          ^^^ This one

那个零只是使fill默认为0,并将align设置为=

=对齐方式的规定如下:

强制填充位放在符号(如果有)之后但数字之前。这用于以“+000000120”形式打印字段。此对齐选项仅适用于数字类型。当“0”紧接着字段宽度时,它成为默认值。

源(Python 3文档)

这需要参数为int,因为字符串没有符号。所以我们只需手动将其设置为正常默认值>(右对齐)。

另请注意,0只是指定了fillalign的默认值。您可以更改两者或仅更改对齐方式。

>>> # 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'

11

str.__format__ 不知道如何处理你的 03 部分。这仅适用于数字:

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

如果您想要将字符串填充为指定长度,请使用rjust函数:

>>> "1".rjust(3, "0")
'001'

7
在我的情况下,我试图给一个字符串进行零填充,而不是一个数字。
解决方案很简单,就是在填充之前将文本转换为数字:
num_as_text = '23'
num_as_num = int(num_as_text)
padded_text = f'{num_as_num:03}'

这是最简单的方法 - 您可以使用 f'{int(num_as_text):03}' 缩减为一行 - 将字符串转换为整数进行填充。 如果需要,您可以进一步将其转换回字符串。 - Apolymoxic

1

自 Python 3.10 版本开始:在宽度字段之前添加 '0' 不再影响字符串的默认对齐方式。

感谢 Serhiy Storchaka 的修复

OP 的代码示例在 Python 3.10+ 中运行良好。但请注意,它返回 100,因为非数字类型的默认 align<

对于旧版本的 Python,请手动添加左对齐字符:"{num:<03}".format(num="1")


谢谢您的更新。我已编辑被接受的答案,以包含这个相关信息。 - bignose

0

您正在尝试将 'string->"1"' 插入一个需要 float->3.44 的位置。请移除引号 "1",即 num=1,这样就可以正常工作了。


-1
只是为了那些通过谷歌搜索并找到这个问答的其他人。
这个错误:
    out_name = track_name_fmt.format(track, song)
ValueError: '=' alignment not allowed in string format specifier

通过使用以下方法进行修复:
out_name = track_name_fmt.format(int(track), song)

强制将track转换为整数解决了问题。

这是对一个稍微不同的问题的回答;它并不构成对这个问题的回答。 - bignose
@bignose 这是对可能帮助其他使用谷歌搜索引擎的错误消息的回答。然而,我鄙视负评,将很快删除这个回答。 - WinEunuuchs2Unix

-4

这种格式是可以接受的

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

但是你指定的占位符方式{num:03}是不正确的。如果你去掉:,那么这个有趣的ValueError就会被一个标准的KeyError替代。


1
这个代码没有达到原作者的意图。他们想要使用format函数来左对齐一个带有填充字符的字符串。 - Aaron Christiansen
啊,我现在明白了。这样更有意义。 - pholtz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接