2010-08-21 12 views
15

Gibt es eine Möglichkeit, python string.format zu verwenden, so dass keine Ausnahme ausgelöst wird, wenn ein Index fehlt, stattdessen eine leere Zeichenfolge eingefügt wird. RechtsPython-String-Format unterdrücken/stille keyerror/indexerror

"i am an example string success" 

jetzt, Python wirft einen KeyError und stoppt Formatierung:

result = "i am an {error} example string {error2}".format(hello=2,error2="success") 

hier sollte Folge sein. Ist es möglich, dieses Verhalten zu ändern?

Dank

Edit:

Es Template.safe_substitute existiert (auch das lässt das Muster intakt stattdessen eine leere Zeichenfolge einzufügen), konnte aber nicht etwas ähnliches für string.format

Die Das gewünschte Verhalten wäre ähnlich wie in PHP.

class Formatter(string.Formatter): 
    def get_value(self,key,args,kwargs): 
    try: 
     if hasattr(key,"__mod__"): 
      return args[key] 
     else: 
      return kwargs[key] 
    except: 
     return "" 

Dies scheint das gewünschte Verhalten zu bieten.

+0

Sie können auch mit 'str.format_map()', wie in [diese Antwort] (http://stackoverflow.com/a/17215533/877069). –

Antwort

5

Leider, nein, es gibt keine solche Möglichkeit, standardmäßig zu tun. Allerdings können Sie es defaultdict liefern oder mit überschriebene __getattr__ Objekt, und wie diese verwenden:

class SafeFormat(object): 
    def __init__(self, **kw): 
     self.__dict = kw 

    def __getattr__(self, name): 
     if not name.startswith('__'): 
      return self.__dict.get(name, '') 

print "i am an {0.error} example string {0.error2}".format(SafeFormat(hello=2,error2="success")) 
i am an example string success 
+1

Danke. Sein benutzerfreundliches, aber wie Fabian erwähnt, behandelt nicht andere Zuordnungsobjekte als dict –

18

str.format() kein Mapping-Objekt erwarten. Versuchen Sie folgendes:

from collections import defaultdict 

d = defaultdict(str) 
d['error2'] = "success" 
s = "i am an {0[error]} example string {0[error2]}" 
print s.format(d) 

Sie machen eine defaultdict mit einer str() Fabrik, die "" zurück. Dann machen Sie einen Schlüssel für das Defaultdict. In der Formatzeichenfolge greifen Sie auf Schlüssel des ersten übergebenen Objekts zu. Dies hat den Vorteil, dass Sie andere Schlüssel und Werte übergeben können, solange Ihr Standarddict das erste Argument für format() ist.

Auch sehen http://bugs.python.org/issue6081

+0

Könnte dieses verbessert werden, indem man ein Formatter-Objekt (Idee von der Fehlerberichtverbindung) anstelle von einem defaultdict verwendet? Auf diese Weise wird keine Änderung an die Formatvariable benötigt. Danke –

+0

Klasse Formatter (String.Formatter): def get_value (self, Schlüssel, args, kwargs): Versuch: wenn hasattr (Taste "__ mod__"): return args [key] sonst: return kwargs [key] Ausnahme: return "" Das funktioniert für mich. Der Vorteil besteht darin, dass kein zusätzliches Standarddict erstellt werden muss. –

+0

Ja, das funktioniert gut. Ich bin nicht sicher, wie man die Strafe eines zusätzlichen Standarddict gegen die Strafe einer zusätzlichen Formatter Klasse + Objekt vergleicht, aber in einigen Situationen könnte es besser sein, besonders wenn es den Code klarer macht. –

2

ich eine Version gemacht, die ähnlich wie Daniel Methode funktioniert aber ohne die {0.x} Attribut Zugriff.

import string  
class SafeFormat(object): 
    def __init__(self, **kw): 
     self.__dict = kw 

    def __getitem__(self, name): 
     return self.__dict.get(name, '{%s}' % name) 



string.Formatter().vformat('{what} {man}', [], SafeFormat(man=2)) 

druckt

'{what} 2' 
12

Die offizielle Lösung (Python 3 Docs) für Strings in Format-Mappings ist die dict Klasse, Unterklasse und die Magie-Methode __missing__() zu definieren. Diese Methode wird aufgerufen, wenn ein Schlüssel fehlt, und was es für die Zeichenfolge Formatierung stattdessen zurück verwendet:

class format_dict(dict): 
    def __missing__(self, key): 
     return "..." 

d = format_dict({"foo": "name"}) 

print("My %(foo)s is %(bar)s" % d) # "My name is ..." 

print("My {foo} is {bar}".format(**d)) # "My name is ..." 
+0

Ich habe gerade versucht, und Sie können: 'einige {Sache}'. Format (Format_dict ('Ihr': Argumente)) Es effektiv zum Schweigen bringen der KeyError und ersetzen Sie das Tag durch was auch immer die __missing__ magische Funktion zurück. – thomas

+1

'.format (** format_dict ({" foo ":" name "}))' kann natürlich auch verwendet werden. Ihr Snippet schlägt jedoch aufgrund eines Syntaxfehlers fehl. Das dict-Entpacken '**' ist obligatorisch für '.format()', dh dicts werden nicht direkt akzeptiert. – CoDEmanX

+0

In der Tat, mein Fehler. – thomas