Comment puis-je imprimer des caractères littéraux entre accolades en chaîne python et également utiliser .format dessus?


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

Donne moi : Key Error: Hello\\

Je veux imprimer la sortie: {Hello} 42



9
Pour ceux qui veulent éviter de doubler les accolades ( {{ }}), utilisez string.Template. Là, vous remplacez les identifiants du formulaire $foo(pratique pour générer du code LaTeX).
Ioannis Filippidis

Pour ceux qui veulent éviter de doubler les accolades et qui ne sont pas opposés à ajouter une autre dépendance à leurs projets Python, il y a aussi Jinja2 qui résout définitivement ce problème, en permettant la syntaxe de délimiteur d'espace réservé personnalisé défini par l'utilisateur.
dreftymac

Réponses:


2072

Vous devez doubler le {{et }}:

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

Voici la partie pertinente de la documentation Python pour la syntaxe des chaînes de format :

Les chaînes de format contiennent des «champs de remplacement» entourés d'accolades {}. Tout ce qui n'est pas contenu entre accolades est considéré comme du texte littéral, qui est copié tel quel dans la sortie. Si vous devez inclure un caractère d'accolade dans le texte littéral, vous pouvez l'échapper en doublant: {{et }}.


264
Donc, si vous voulez imprimer "{42}", vous utiliseriez "{{{0}}}".format(42)!
Hugh

7
Et si vous voulez une seule attelle bouclée? "{ something { } {value}".format(42)ne fonctionne pas.
AJP

14
"{{" .format () et "}}". format () imprime les accolades simples. Dans votre exemple: imprimez "{{quelque chose {{}} {0}". Format (42) imprimera "{quelque chose {} 42".
Mark Visser

2
Qu'est-ce que cela {0}signifie?
CodyBugstein

6
@Imray: {0}fait référence au premier argument de .format(). Vous pouvez imprimer plusieurs valeurs comme {0} {1} {2}tant que vous donnez le même nombre d'arguments à .format(). Voir docs.python.org/library/string.html#format-examples pour des exemples détaillés.
Greg Hewgill

74

Vous y échappez en doublant les accolades.

Par exemple:

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

60

Python 3.6+ (2017)

Dans les versions récentes de Python, on utiliserait des chaînes f (voir aussi PEP498 ).

Avec les chaînes f, on doit utiliser double {{ou}}

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

produit le désiré

 {Hello} 42

Si vous devez résoudre une expression entre crochets au lieu d'utiliser du texte littéral, vous aurez besoin de trois ensembles de crochets:

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

produit

{hello}

46

Le PO a écrit ce commentaire:

J'essayais de formater un petit JSON à certaines fins, comme ceci: '{"all": false, "selected": "{}"}'.format(data)pour obtenir quelque chose comme{"all": false, "selected": "1,2"}

Il est assez courant que le problème des "accolades échappées" apparaisse lors du traitement avec JSON.

Je suggère de faire ceci:

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

C'est plus propre que l'alternative, qui est:

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

L'utilisation de la jsonbibliothèque est définitivement préférable lorsque la chaîne JSON devient plus compliquée que l'exemple.


1
Amen! Cela peut sembler plus de travail, mais utiliser les bibliothèques pour faire ce que les bibliothèques sont censées faire par rapport à couper les coins ronds ... fait de meilleures choses.
Kaolin Fire

1
Mais l'ordre des clés dans un objet Python n'est pas garanti ... Pourtant, la bibliothèque JSON est garantie de sérialiser de manière JSON.
wizzwizz4

2
wizzwizz4: Bon point. À partir de Python 3.6, les dictionnaires sont ordonnés par insertion, ce ne sera donc pas un problème. Les versions de Python entre 2.7 et 3.5 peuvent utiliser OrderedDict à partir de la bibliothèque de collections.
twasbrillig

24

Essayez de faire ceci:

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


14

Bien que pas mieux, juste pour la référence, vous pouvez également le faire:

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

Cela peut être utile par exemple lorsque quelqu'un veut imprimer {argument}. C'est peut-être plus lisible que'{{{}}}'.format('argument')

Notez que vous omettez les positions d'argument (par exemple {}au lieu de {0}) après Python 2.7


5

Si vous allez faire cela beaucoup, il pourrait être bon de définir une fonction utilitaire qui vous permettra d'utiliser à la place des substituts d'accolade arbitraires, comme

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

Notez que cela fonctionnera soit avec des crochets étant une chaîne de longueur 2 ou un itérable de deux chaînes (pour les délimiteurs à plusieurs caractères).


Pensé à cela aussi. Bien sûr, cela fonctionnera aussi et l'algorithme est plus simple. Mais, imaginez que vous ayez beaucoup de texte comme celui-ci, et que vous vouliez juste le paramétrer ici et là. Chaque fois que vous créez une chaîne d'entrée, vous ne voudriez pas remplacer tous ces accolades manuellement. Vous voudriez simplement «déposer» vos paramétrisations ici et là. Dans ce cas, je pense que cette méthode est à la fois plus facile à penser et à accomplir du point de vue de l'utilisateur. J'ai été inspiré par la commande 'sed' de linux qui a des capacités similaires pour choisir arbitrairement votre délimiteur en fonction de ce qui est pratique.
tvt173

En bref, je préfère que la fonction utilitaire soit un peu plus complexe que ce soit pénible dans @ $$ à utiliser à chaque fois. Veuillez me faire savoir si j'ai mal compris votre proposition.
tvt173

Je suis allé de l'avant et j'ai ajouté une courte démo à mon espace public.lab github.com/dreftymac/public.lab/blob/master/topic/python/…
dreftymac

3

J'ai récemment rencontré cela, car je voulais injecter des chaînes dans du JSON préformaté. Ma solution a été de créer une méthode d'aide, comme ceci:

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

Vous pouvez alors faire quelque chose comme:

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

Obtient le travail si les performances ne sont pas un problème.


Simple ET élégant à intégrer dans le code existant avec peu de modifications requises. Merci!
Column01

2

Si vous devez conserver deux accolades dans la chaîne, vous avez besoin de 5 accolades de chaque côté de la variable.

>>> myvar = 'test'
>>> "{{{{{0}}}}}".format(myvar)
'{{test}}'

Pour ceux qui utilisent des cordes f, utilisez 4 accolades bouclées de chaque côté au lieu de 5
TerryA

0

La raison en est que {}la syntaxe de .format()donc dans votre cas .format()ne la reconnaît pas {Hello}, elle a donc généré une erreur.

vous pouvez le remplacer en utilisant des accolades doubles {{}},

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

ou

essayez %sde mettre en forme le texte,

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

0

Je suis tombé sur ce problème en essayant d'imprimer du texte, que je peux copier-coller dans un document Latex. J'étends cette réponse et utilise les champs de remplacement nommés:

Disons que vous voulez imprimer un produit de plusieurs variables avec des indices tels que entrez la description de l'image ici, qui, dans Latex, serait le $A_{ 0042 }*A_{ 3141 }*A_{ 2718 }*A_{ 0042 }$ code suivant pour les champs nommés de sorte que pour de nombreux indices, il reste lisible:

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 vous ne souhaitez imprimer qu'une seule accolade (par exemple {), vous pouvez l'utiliser {{, et vous pouvez ajouter plus d'accolades plus tard dans la chaîne si vous le souhaitez. Par exemple:

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

Lorsque vous essayez simplement d'interpoler des chaînes de code, je suggère d'utiliser jinja2 qui est un moteur de modèle complet pour Python, c'est-à-dire:

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))

Donc, vous ne serez pas obligé de dupliquer les accolades comme le suggère tout un tas d'autres réponses


-3

Vous pouvez le faire en utilisant la méthode de chaîne brute en ajoutant simplement le caractère «r» sans guillemets avant la chaîne.

# to print '{I am inside braces}'
print(r'{I am inside braces}')

salut! Vous voudrez peut-être revérifier cela; Impressions Python 3.7 \{I am inside braces\}.
Teodor

1
@Teodor désolé pour ça. Maintenant, j'ai corrigé cela en imprimant sous forme de chaîne brute.
Harsh Aggarwal
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.