¿Cómo puedo imprimir caracteres literales con llaves en una cadena y también usar .format en ella?

1914
x = " \{ Hello \} {0} "
print(x.format(42))

me da: Key Error: Hello\\

Quiero imprimir la salida: {Hello} 42

3
  • 1
    Véase también: stackoverflow.com/questions/35574349 6 de diciembre de 2016 a las 5:11
  • 15
    Para aquellos que quieren evitar doblar llaves ( {{ }}), use string.Template. Allí sustituye los identificadores del formulario $foo(útil para generar código LaTeX). 11 de enero de 2018 a las 5:51
  • 1
    Para aquellos que quieren evitar las llaves dobles y que no son reacios a agregar otra dependencia a sus proyectos de Python, también existe Jinja2 que definitivamente resuelve este problema, al permitir la sintaxis del delimitador de marcador de posición personalizado definido por el usuario. 15/01/20 a las 20:07
2666

Necesita duplicar {{y }}:

>>> x = " {{ Hello }} {0} "
>>> print(x.format(42))
' { Hello } 42 '

Aquí está la parte relevante de la documentación de Python para la sintaxis de cadenas de formato :

Format strings contain “replacement fields” surrounded by curly braces {}. Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }}.

14
  • 320
    Entonces, si desea imprimir "{42}", ¡usaría "{{{0}}}".format(42)!
    hughes
    24/07/2013 a las 20:21
  • 12
    ¿Qué pasa si quieres un único tirante rizado? "{ something { } {value}".format(42)no funciona.
    AJP
    2 oct 2013 a las 10:10
  • 22
    "{{" .format () y "}}". format () imprimen llaves simples. En su ejemplo: imprimir "{{algo {{}} {0}". El formato (42) imprimirá "{algo {} 42". 18/10/2013 a las 21:19
  • 2
    ¿Qué {0}significa? 21 feb 2014 a las 1:27
  • 9
    @Imray: se {0}refiere al primer argumento de .format(). Puede imprimir más de un valor {0} {1} {2}como siempre que le dé el mismo número de argumentos .format(). Consulte docs.python.org/library/string.html#format-examples para ver ejemplos extensos. 21 feb 2014 a las 1:30
130

Python 3.6+ (2017)

En las versiones recientes de Python, se usarían cadenas f (ver también PEP498 ).

Con f-strings uno debe usar doble {{o}}

n = 42  
print(f" {{Hello}} {n} ")

produce el deseado

 {Hello} 42

Si necesita resolver una expresión entre corchetes en lugar de usar texto literal, necesitará tres conjuntos de corchetes:

hello = "HELLO"
print(f"{{{hello.lower()}}}")

produce

{hello}
6
  • 2
    De my_greet = "HELLO"puede obtener {hello}como salida, usando solo 2 conjuntos de corchetes, con print(f"{ {my_greet.lower()} }"). Deje un espacio entre corchetes.
    yrnr
    20/07/20 a las 7:07
  • 1
    Esta debería ser ahora la respuesta aceptada si está utilizando Python3.6 + en los tiempos de la rona.
    Gwi7d31
    20/11/20 a las 18:27
  • @ Gwi7d31 No, las cadenas de f no sustituyen a str.format(). Por ejemplo, esta respuesta que escribí no es posible con f-strings ya que la plantilla proviene de la entrada, no del código fuente. 20 de mayo a las 18:20
  • 1
    @wjandrea su enlace realmente no pertenece a la pregunta de OP. El OP quiere mantener las llaves mientras las elimina en su respuesta vinculada a través de .format () y el método de desempaquetado de su diccionario. Si desea conservar {} en Python 3.6 o superior y desea insertar un valor en una cadena, this is the way. Esa es la pregunta que nos ocupa. Tampoco dije que las cadenas f son un reemplazo para .format (). Tú dijiste eso.
    Gwi7d31
    26 de mayo a las 3:06
  • @Gwi Lo que estoy diciendo es que esta pregunta se trata str.format(), no de f-strings, y no son compatibles entre sí. 26 de mayo a las 3:18
90

Se escapa doblando los tirantes.

P.ej:

x = "{{ Hello }} {0}"
print(x.format(42))
0
56

El OP escribió este comentario:

I was trying to format a small JSON for some purposes, like this: '{"all": false, "selected": "{}"}'.format(data) to get something like {"all": false, "selected": "1,2"}

Es bastante común que surja el problema de "frenar llaves" cuando se trabaja con JSON.

Sugiero hacer esto:

import json
data = "1,2"
mydict = {"all": "false", "selected": data}
json.dumps(mydict)

Es más limpio que la alternativa, que es:

'{{"all": false, "selected": "{}"}}'.format(data)

jsonDefinitivamente es preferible usar la biblioteca cuando la cadena JSON se vuelve más complicada que el ejemplo.

4
  • 1
    ¡Amén! Puede parecer más trabajo, pero usar bibliotecas para hacer lo que se supone que deben hacer las bibliotecas en lugar de tomar atajos ... mejora las cosas. 10/04/2018 a las 19:12
  • 1
    Pero el orden de las claves en un objeto Python no está garantizado ... Aún así, se garantiza que la biblioteca JSON se serialice de forma JSON. 30 de junio de 2018 a las 8:34
  • 2
    wizzwizz4: Buen punto. Desde Python 3.6 en adelante, los diccionarios están ordenados por inserción, por lo que no sería un problema. Las versiones de Python entre 2.7 y 3.5 pueden usar OrderedDict de la biblioteca de colecciones. 1 de julio de 2018 a las 18:47
  • 1
    La alternativa también es terriblemente incorrecta si, por ejemplo, data = 'foo"'porque "el valor de en datano se escapará correctamente.
    chepner
    31/12/20 a las 21:42
28

Intenta hacer esto:

x = " {{ Hello }} {0} "
print x.format(42)
26

Prueba esto:

x = "{{ Hello }} {0}"

16

Aunque no es mejor, solo como referencia, también puede hacer esto:

>>> x = '{}Hello{} {}'
>>> print x.format('{','}',42)
{Hello} 42

Puede ser útil, por ejemplo, cuando alguien quiere imprimir {argument}. Quizás sea más legible que'{{{}}}'.format('argument')

Tenga en cuenta que omite las posiciones de los argumentos (por ejemplo, en {}lugar de {0}) después de Python 2.7

0
9

Si necesita mantener dos llaves en la cuerda, necesita 5 llaves a cada lado de la variable.

>>> myvar = 'test'
>>> "{{{{{0}}}}}".format(myvar)
'{{test}}'
2
  • 2
    Para aquellos que usan f-strings, use 4 llaves a cada lado en lugar de 5
    TerryA
    19 de septiembre de 2019 a las 7:11
  • 1
    @TerryA no hay diferencia en el comportamiento de las llaves entre .format y f-strings. El código a = 1; print('{{{{{a}}}}}'.format(a=a))produce los mismos resultados que a = 1; print(f'{{{{{a}}}}}'). 10 de junio a las 19:07
6

Si va a hacer mucho esto, podría ser bueno definir una función de utilidad que le permita usar sustitutos de llaves arbitrarios, como

def custom_format(string, brackets, *args, **kwargs):
    if len(brackets) != 2:
        raise ValueError('Expected two brackets. Got {}.'.format(len(brackets)))
    padded = string.replace('{', '{{').replace('}', '}}')
    substituted = padded.replace(brackets[0], '{').replace(brackets[1], '}')
    formatted = substituted.format(*args, **kwargs)
    return formatted

>>> custom_format('{{[cmd]} process 1}', brackets='[]', cmd='firefox.exe')
'{{firefox.exe} process 1}'

Tenga en cuenta que esto funcionará si los corchetes son una cadena de longitud 2 o una iterable de dos cadenas (para delimitadores de varios caracteres).

3
  • Pensé en eso también. Por supuesto, eso también funcionará y el algoritmo es más simple. Pero, imagina que tienes mucho texto como este y solo quieres parametrizarlo aquí y allá. Cada vez que crea una cadena de entrada, no querrá reemplazar todas esas llaves manualmente. Solo querrá 'colocar' sus parametrizaciones aquí y allá. En este caso, creo que este método es más fácil de pensar y de lograr desde la perspectiva del usuario. Me inspiré en el comando 'sed' de Linux, que tiene capacidades similares para elegir arbitrariamente su delimitador según lo que sea conveniente.
    tvt173
    1 de diciembre de 2016 a las 18:53
  • En resumen, prefiero que la función de utilidad sea un poco más compleja a que sea una molestia en el @ $$ usarla cada vez. Por favor, avíseme si entendí mal su propuesta.
    tvt173
    1 de diciembre de 2016 a las 18:56
  • Seguí adelante y agregué una breve demostración a mi espacio public.lab github.com/dreftymac/public.lab/blob/master/topic/python/… 1 de diciembre de 2016 a las 20:56
4

Recientemente me encontré con esto, porque quería inyectar cadenas en JSON preformateado. Mi solución fue crear un método auxiliar, como este:

def preformat(msg):
    """ allow {{key}} to be used for formatting in text
    that already uses curly braces.  First switch this into
    something else, replace curlies with double curlies, and then
    switch back to regular braces
    """
    msg = msg.replace('{{', '<<<').replace('}}', '>>>')
    msg = msg.replace('{', '{{').replace('}', '}}')
    msg = msg.replace('<<<', '{').replace('>>>', '}')
    return msg

Luego puede hacer algo como:

formatted = preformat("""
    {
        "foo": "{{bar}}"
    }""").format(bar="gas")

Hace el trabajo si el rendimiento no es un problema.

3
  • Simple Y elegante para integrar en el código existente con pocas modificaciones necesarias. ¡Gracias! 12 de mayo de 2020 a las 16:22
  • por supuesto, asumiendo que su texto nunca contenía ninguno <<<y >>>para empezar, de lo contrario, se sobrescribirán. ¡Es mejor usar estrategias de escape para mayor confiabilidad!
    axolotl
    25 de agosto a las 15:39
  • ¿Qué estrategia de escape sugieres? De todos modos, conoces el texto de tu plantilla y puedes modificar las cadenas mágicas en caso de que te preocupes por los conflictos. 27 de agosto a las 12:38
2

Usé un {{}} doble para evitar la inyección de valor de fstring,

por ejemplo, aquí está mi declaración UPDATE de Postgres para actualizar una columna de matriz de enteros que toma la expresión de {} para capturar la matriz, es decir:

puertos = '{100,200,300}'

con fstrings su,

ports = [1,2,3]

query = f"""
   UPDATE table SET ports = '{{{ports}}}' WHERE id = 1
"""

la declaración de consulta real será,

UPDATE table SET ports = '{1,2,3}'

que es un estado de postgres válido

2

Si desea imprimir solo un lado de la llave:

a=3
print(f'{"{"}{a}')
>>> {3
2

f-strings (python 3)

Puede evitar tener que duplicar las llaves usando f-strings SOLAMENTE para las partes de la cadena donde desea que se aplique f-magic, y usando cadenas regulares (tontas) para todo lo que sea literal y pueda contener un especial 'inseguro' caracteres. Deje que Python haga la unión de cadenas por usted simplemente apilando varias cadenas juntas.

number = 42
print(" { Hello }"  
f" {number} " 
"{ thanks for all the fish }")

### OUTPUT:
{ Hello } 42 { thanks for all the fish }

NOTE: Line breaks between the strings are NOT required. I have only added them for readability. You could as well write the code above as shown below:

⚠️ WARNING: This might hurt your eyes or make you dizzy!

print("{Hello}"f"{number}""{thanks for all the fish}")
1

La razón es {}que la sintaxis de, .format()en su caso .format(), no reconoce, {Hello}por lo que arrojó un error.

puede anularlo usando llaves dobles {{}},

x = " {{ Hello }} {0} "

o

probar el %sformato de texto,

x = " { Hello } %s"
print x%(42)  
1

Llego ridículamente tarde a esta fiesta. Estoy teniendo éxito colocando los corchetes en el elemento de reemplazo, así:

print('{0} {1}'.format('{hello}', '{world}'))

que imprime

{hello} {world}

Estrictamente hablando, esto no es lo que pide OP, ya que quiere las llaves en la cadena de formato, pero esto puede ayudar a alguien.

1

Puede utilizar un "muro de citas" para separar la parte de cadena formateada de la parte de cadena normal.

De:

print(f"{Hello} {42}")

para

print("{Hello}"f" {42}")

Un ejemplo más claro sería

string = 10
print(f"{string} {word}")

Producción:

NameError: name 'word' is not defined

Ahora, agregue el muro de cotizaciones así:

string = 10
print(f"{string}"" {word}")

Producción:

10 {word}
2
  • 1
    Esto se parece más a una concatenación, pero es una buena idea. 14 de junio a las 6:49
  • Yo desaconsejaría esto: está usando una característica del lenguaje que es en sí controvertida y que Guido describe como un error (concatenación implícita de cadenas) y la usa de una manera que es, en sí misma, inusual y, por lo tanto, confusa. A muchas personas que se les ocurra esto les costará entender lo que está sucediendo. Básicamente, va f "{cadena}" + "{palabra}", lo cual es simple y directo, pero lo hace de una manera más confusa. Me recuerda al falso 'obtener el elemento único de un operador de conjunto', = como se usa en elem, = {'single_element'} que funciona pero solo causa confusión. 25 de junio a las 14:31
0

Me encontré con este problema al intentar imprimir texto, que puedo copiar y pegar en un documento de Latex. Extiendo esta respuesta y uso campos de reemplazo con nombre:

Supongamos que desea imprimir un producto de múltiples variables con índices como ingrese la descripción de la imagen aquí, que en Latex sería $A_{ 0042 }*A_{ 3141 }*A_{ 2718 }*A_{ 0042 }$ El siguiente código hace el trabajo con campos con nombre para que para muchos índices sea legible:

idx_mapping = {'i1':42, 'i2':3141, 'i3':2178 }
print('$A_{{ {i1:04d} }} * A_{{ {i2:04d} }} * A_{{ {i3:04d} }} * A_{{ {i1:04d} }}$'.format(**idx_mapping))
-1

Si solo desea imprimir una llave (por ejemplo {), puede usar {{, y puede agregar más llaves más adelante en la cadena si lo desea. Por ejemplo:

>>> f'{{ there is a curly brace on the left. Oh, and 1 + 1 is {1 + 1}'
'{ there is a curly brace on the left. Oh, and 1 + 1 is 2'
-1

Si necesita llaves dentro de una plantilla de cadena f que se pueda formatear, debe generar una cadena que contenga dos llaves dentro de un conjunto de llaves para la cadena f:

css_template = f"{{tag}} {'{{'} margin: 0; padding: 0;{'}}'}"
for_p = css_template.format(tag="p")
# 'p { margin: 0; padding: 0;}'
2
  • esta pregunta no se trataba de f-strings, y en mi opinión, la combinación de f-strings y formato de esta manera hace que el código sea bastante ilegible
    avigil
    25 feb a las 17:07
  • Sin embargo, es el primer resultado que aparece cuando buscas en Google cómo poner llaves en las cadenas de f de python, y sí, estoy de acuerdo en que no es bonito, pero a veces solo lo necesitas. 26 de febrero a las 8:28
-1

¿O simplemente parametrizar el propio soporte? Probablemente muy detallado.

x = '{open_bracket}42{close_bracket}'.format(open_bracket='{', close_bracket='}') 
print(x)
# {42}
-2

Cuando solo intente interpolar cadenas de código, sugeriría usar jinja2, que es un motor de plantillas con todas las funciones para Python, es decir:

from jinja2 import Template

foo = Template('''
#include <stdio.h>

void main() {
    printf("hello universe number {{number}}");
}
''')

for i in range(2):
    print(foo.render(number=i))

Por lo tanto, no se le obligará a duplicar llaves como sugieren todas las otras respuestas

1
  • 1
    Estoy de acuerdo en que evitar la duplicación de llaves es algo bueno, pero en lugar de buscar jinja2, simplemente usaría la propia string.Templateclase de Python , que es lo suficientemente poderosa para este tipo de cosas. 3 de agosto a las 16:06
-3

Puede hacer esto usando el método de cadena sin formato simplemente agregando el carácter 'r' sin comillas antes de la cadena.

# to print '{I am inside braces}'
print(r'{I am inside braces}')
2
  • ¡Hola! Es posible que desee volver a comprobarlo; Impresiones de Python 3.7 \{I am inside braces\}.
    Teodor
    14/09/19 a las 11:34
  • 1
    @Teodor lo siento por eso. Ahora arreglé esto imprimiendo como cadena sin procesar. 21/09/19 a las 13:55
-4

Utilice secuencias de escape para escapar de las llaves en la f-string. Por ejemplo: print (f '{a = {1}}')

1
  • 4
    OP usó secuencias de escape e informó que no funcionaron. El ejemplo aquí no se compila. Esta respuesta no agrega ningún valor a las quince respuestas publicadas anteriormente. 23/06/20 a las 0:14