Ignora str.format (** foo) si la clave no existe en foo

Estoy tratando de obtener una plantilla de correo electrónico juntos. El contenido del mensaje dependerá de los valores dentro de un diccionario. Sin embargo, es posible que el diccionario no contenga todas las claves cada vez.

Actualmente esto está bien, ya que todos los valores están en el diccionario ( 'Title' , 'Surname' , 'Additional Details' ):

 practise_dict = {"Additional Details":"blah blah blah blah", "Title": "Mr", "Surname": "Smith", "URL": "/test/tester"} msg = """From: John Smith  To: {Title} {Surname}  MIME-Version: 1.0 Content-type: text/html Subject: New Website Enquiry This is an e-mail message to be sent in HTML format {Additional Details} This is HTML message. 

This is headline.

`""".format(**practise_dict) print(msg)

En la variable msg estoy tratando de crear mi ‘plantilla’. Esto significa que necesito tener todos los elementos posibles que podrían estar en el diccionario.

Por ejemplo, la siguiente pieza fallaría, ya que está buscando 'Date' que no existe en este diccionario:

 practise_dict = {"Additional Details":"blah blah blah blah", "Title": "Mr", "Surname": "Smith", "URL": "/test/tester"} msg = """From: John Smith  To: {Title} {Surname}  MIME-Version: 1.0 Content-type: text/html Subject: New Website Enquiry This is an e-mail message to be sent in HTML format {Additional Details} {Date} This is HTML message. 

This is headline.

`""".format(**practise_dict) print(msg)

¿Hay alguna forma de pedirle que ignore una sustitución de cadena si no existe como clave en el diccionario de búsqueda?

Puedes usar Template y safe_substitute para eso:

 from string import Template practise_dict = {"Additional_Details":"blah blah blah blah", "Title": "Mr", "Surname": "Smith", "URL": "/test/tester"} msg = """From: John Smith  To: $Title $Surname  MIME-Version: 1.0 Content-type: text/html Subject: New Website Enquiry This is an e-mail message to be sent in HTML format $Additional_Details $Date This is HTML message. 

This is headline.

`""" s = Template(msg).safe_substitute(**practise_dict) print(s)

SALIDA

 From: John Smith  To: Mr Smith  MIME-Version: 1.0 Content-type: text/html Subject: New Website Enquiry This is an e-mail message to be sent in HTML format blah blah blah blah $Date This is HTML message. 

This is headline.

No creo que haya una manera de decirle al format que algunas sustituciones son opcionales. Sin embargo, aquí hay dos soluciones.

Si solo falta un campo, intente algo como:

 msg = """...""".format(Date=practise_dict.pop("Date", ""), # handle optional field **practise_dict) # pass the rest as before 

Sin embargo, tenga en cuenta que esto modifica practise_dict , y será incómodo si hay varios valores con los que lidiar.

Si faltan varios campos, o si no desea modificar el diccionario, probablemente sea preferible lo siguiente:

 defaults = {"Date": "", "Additional Details": ""} # define optional fields defaults.update(practise_dict) # override user data where available msg = """...""".format(**defaults) 

Ambos enfoques seguirán fallando para las claves para las que no ha proporcionado explícitamente una alternativa, lo que le permite hacer que algunos campos sean obligatorios.

En caso de que aún no conozcas las llaves:

Solo puede escribir una subclase dict, que devolverá la clave si no se encuentra en el diccionario:

 class FailsafeDict(dict): def __getitem__(self, item): try: return super().__getitem__(item) except KeyError: return "{" + str(item) + "}" # end try # end def # end class 

Esto funciona anulando la función __getitem__(item) , que maneja la llamada dict[item] .

Puedes usarlo así:

 f = FailsafeDict({"yo": "lo", "foo": "bar"}) text = "{yo}! {lol}! {foo}!".format(**f) print(text) 

Que imprime lo! {lol}! bar! lo! {lol}! bar! .

En tu caso eso sería

 msg = """...""".format(**FailsafeDict(practise_dict))