14

EDITED

I have to format a string with values from a dictionary but the string already contains curly brackets. E.g.:

raw_string = """
    DATABASE = {
        'name': '{DB_NAME}'
   }
"""

But, of course, raw_string.format(my_dictionary) results in KeyErro.

Is there a way to use different symbols to use with .format()?

This is not a duplicate of How can I print literal curly-brace characters in python string and also use .format on it? as I need to keep curly brackets just as they are and use a different delimiter for .format.

Don
  • 16,928
  • 12
  • 63
  • 101
  • 1
    See also: https://pyformat.info/#custom_1 – dreftymac Dec 01 '16 at 02:13
  • 1
    See also: http://stackoverflow.com/questions/5466451/how-can-i-print-a-literal-characters-in-python-string-and-also-use-format – dreftymac Dec 01 '16 at 20:33
  • See also: https://stackoverflow.com/questions/16433589/change-string-format-delimeters-in-python – dreftymac Oct 29 '17 at 09:33
  • See also: https://stackoverflow.com/questions/34214945/advanced-python-string-formatting-with-custom-placeholders – dreftymac Oct 29 '17 at 09:36
  • See also: (str.format missing values) https://stackoverflow.com/questions/8997279/substituting-missing-values-in-python – dreftymac Oct 29 '17 at 09:41
  • See also: (missing name-value pairs) https://stackoverflow.com/questions/17215400/python-format-string-unused-named-arguments – dreftymac Jul 01 '18 at 15:07
  • This question is very unclear as it stands, yet well-SEOed. What possible set of constraints means that you're able to change to using different delimiters around your format placeholders, but *not* able to escape delimiters elsewhere in your format string? It's not explained, and it leaves it unclear whether you actually understand the answer at the duplicate. I'm voting to delete, because the combination of an unclear question and a duplicate that doesn't actually achieve the task asked for in this question's title makes this unhelpful even as a signpost pointing Google visitors to the dupe. – Mark Amery Feb 01 '19 at 19:35
  • 1
    @MarkAmery I updated my question (it was messy indeed); is it more clear now? – Don Feb 04 '19 at 16:32
  • "This is not a duplicate of" - **yes, it is**. "I need to do it a different way" doesn't make it a different question. First off, there isn't necessarily a different way; second, a "need" isn't established; third, if there were a different way, it would belong as another answer on that question instead. – Karl Knechtel Jan 22 '23 at 04:13

2 Answers2

15

I don't think it is possible to use alternative delimiters. You need to use double-curly braces {{ }} for curly braces that you don't want to be replaced by format():

inp = """
DATABASE = {{
    'name': '{DB_NAME}'
}}"""

dictionary = {'DB_NAME': 'abc'}
output = inp.format(**dictionary)
print(output)

Output

DATABASE = {
    'name': 'abc'
}
gtlambert
  • 11,711
  • 2
  • 30
  • 48
  • Nice answer. For further reference, http://stackoverflow.com/questions/5466451/how-can-i-print-a-literal-characters-in-python-string-and-also-use-format – sarker306 Feb 23 '16 at 10:15
  • 1
    Mhm... my string comes from a complex file (Django's settings.py) and I'd prefer to keep the template as similar as the file it comes from. Of course I could do double sostitution, but I was looking for a more elegant solution – Don Feb 23 '16 at 10:44
3

Using custom placeholder tokens with python string.format()

Context

  • python 2.7
  • string.format()
  • alternative approach that allows custom placeholder syntax

Problem

We want to use custom placeholder delimiters with python str.format()

  • string.format() is powerful, but no native support for placeholder delimiter modification.
  • string.format() uses curly-brace which is very common and and causes Delimiter collision
  • string.format() default workaround is to double-up the delimiters, which can be cumbersome.

Solution

We write a custom class that extends native python str.format()

  • extend native python string.Formatter with custom class
  • configure string.format() to support arbitrary delimiter placeholder syntax
  • permit other enhancements such as custom formatters and filters

Example001: Demo use of a custom ReFormat class

  • we wrote a custom ReFormat class that extends python str.format()
# import custom class
import ReFormat

# prepare source data
odata = { "fname" : "Planet",
          "lname" : "Earth",
          "age"   : "4b years",
         }

# format output using .render() 
# method of custom ReFormat class
#
vout = ReFormat.String("Hello <%fname%> <%lname%>!",odata).render()
print(vout)

Pitfalls

  • requires extension class to str.format()
  • not intended as a substitute for full-blown sandbox-compatible templating solution
  • str.format has a problem with exact preservation of whitespace around curly-brace when using this kind of approach
dreftymac
  • 31,404
  • 26
  • 119
  • 182
  • How does it compare with alternative templating systems like pystache https://github.com/defunkt/pystache ? – Don Dec 20 '16 at 15:37
  • 1
    This approach is not a strong substitute for a full-blown template system, because those systems are designed to permit designers with no programming experience to do basic tasks. This approach is more compatible with a python-centered project where most or all of the people interacting with the code will know some python. It's basically a couple notches above str.format() all by itself, and a couple notches below Jinja2. – dreftymac Dec 20 '16 at 17:20
  • The github link is now dead. – cyberSingularity Sep 04 '18 at 11:13
  • 1
    Where"s ReFormat implementation? – fx-kirin Feb 21 '20 at 01:05