简体   繁体   English

string.Formatter抛出KeyError''

[英]string.Formatter throws KeyError ''

I want to print out key+value pairs like in this question , 我想在这个问题中打印出键+值对,

key a:         1
key ab:        2
key abc:       3
       ^ this colon is what I want

but I don't like the answer there and I tried to subclass string.Formatter like this: 但我不喜欢那里的答案,我试图像这样string.Formatter

from __future__ import print_function

from string import Formatter

class KeyFormatter(Formatter):
    def parse(self, fmtstr):
        res = super(KeyFormatter, self).parse(fmtstr)
        #for r in res:
        #    print(r)
        return res

kf = KeyFormatter()
w = 10

x = dict(a=1, ab=2, abc=3)

for k in sorted(x):
    v = x[k]
    print(kf.format('key {::<{}} {}', k, w, v))

I want to debug the parsing to see if I can get at the extra ' : ' inserted in the format string but this throws a 我想调试解析,看看我是否可以在格式字符串中插入额外的' : ',但这会抛出一个

KeyError: '' in both Python 2.7 and 3.4. KeyError:在Python 2.7和3.4中都有''。 If I uncomment the for loop to see what is going in the error goes away, but the final print statement then only shows a newline. 如果我取消注释for循环以查看错误中的内容消失,但最终的print语句只显示换行符。

When I make the last line: 当我做最后一行时:

print('key {:<{}} {}'.format(k, w, v))

this works (with spaces after the key), and when I do: 这工作(键后有空格),当我这样做时:

print('key {::<{}} {}'.format(k, w, v))

I get multiple ':' instead of spaces. 我得到多个':'而不是空格。 But no KeyError. 但没有KeyError。

Why do I get the KeyError ? 为什么我会得到KeyError How can I debug this? 我该怎么调试呢?

There are two somewhat related problems here, the simple answer to how to debug is: you can't, at least not with print statements, or anything itself using string formatting because that happens during another string format and destroys the state of the formatter. 这里有两个有些相关的问题,如何调试的简单答案是:你不能,至少不能使用print语句,或者使用字符串格式化的任何东西,因为这种情况发生在另一种字符串格式中并破坏了格式化程序的状态。

That it throws an error is caused by the fact that string.Formatter() doesn't support empty fields, this was an addition to the formatting going from 2.6 to 3.1 (and 2.7), which is in the C code, but not reflected in the string module. 它抛出一个错误是由于string.Formatter()不支持空字段的事实,这是格式从2.6到3.1(和2.7)的补充,这是在C代码中,但没有反映在string模块中。

You can simulate the new behavior by subclassing the class MyFormatter : 您可以通过MyFormatterMyFormatter来模拟新行为:

from __future__ import print_function

from string import Formatter
import sys

w = 10
x = dict(a=1, ab=2, abc=3)

if sys.version_info < (3,):
    int_type = (int, long)
else:
    int_type = (int)    

class MyFormatter(Formatter):

    def vformat(self, *args):
        self._automatic = None
        return super(MyFormatter, self).vformat(*args)

    def get_value(self, key, args, kwargs):
        if key == '':
            if self._automatic is None:
                self._automatic = 0
            elif self._automatic == -1:
                raise ValueError("cannot switch from manual field specification "
                                 "to automatic field numbering")
            key = self._automatic
            self._automatic += 1
        elif isinstance(key, int_type):
            if self._automatic is None:
                self._automatic = -1
            elif self._automatic != -1:
                raise ValueError("cannot switch from automatic field numbering "
                                 "to manual field specification")
        return super(MyFormatter, self).get_value(key, args, kwargs)

that should get rid of the KeyError . 应该摆脱KeyError After that you should override the method format_field instead of parse : 之后你应该覆盖方法format_field而不是parse

if sys.version_info < (3,):
    string_type = basestring
else:
    string_type = str

class TrailingFormatter(MyFormatter):
    def format_field(self, value, spec):
        if isinstance(value, string_type) and len(spec) > 1 and spec[0] == 't':
            value += spec[1]  # append the extra character
            spec = spec[2:]
        return super(TrailingFormatter, self).format_field(value, spec)

kf = TrailingFormatter()
w = 10

for k in sorted(x):
    v = x[k]
    print(kf.format('key {:t:<{}} {}', k, w, v))

and get: 得到:

key a:         1
key ab:        2
key abc:       3

Note the format specifier ( t ) that introduces the trailing character in the format string. 请注意格式说明符( t ),它在格式字符串中引入尾随字符。

The Python formatting routines are actually smart enough to let you insert the trailing character in the string just like the width formatting: Python格式化例程实际上足够聪明,可以让您在字符串中插入尾随字符,就像宽度格式一样:

    print(kf.format('key {:t{}<{}} {}', k, ':', w, v))

gives the same result and lets you dynamically change the ' : ' 给出相同的结果,让你动态改变' : '

You can also change format_field to be: 您还可以将format_field更改为:

    def format_field(self, value, spec):
        if len(spec) > 1 and spec[0] == 't':
            value = str(value) + spec[1]  # append the extra character
            spec = spec[2:]
        return super(TrailingFormatter, self).format_field(value, spec)

and hand in any type: 并交给任何类型:

print(kf.format('key {:t{}<{}} {}', (1, 2), '@', 10, 3))

to get: 要得到:

key (1, 2)@    3

but since you convert the value to a string before handing it to Formatter.formatfield() that might get you a different result if str(val) gets you a different value than using {0}.format(val) and/or with options after t: that only apply to non-string types (such as + and - ) 但是,因为在将值转换为字符串之前将值转换为Formatter.formatfield() ,如果str(val)获得的值与使用{0}.format(val)和/或选项不同,则可能会得到不同的结果在t:之后t:仅适用于非字符串类型(例如+-

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM