Reputation: 9682
I am having a problem like
In [5]: x = "this string takes two like {one} and {two}"
In [6]: y = x.format(one="one")
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-6-b3c89fbea4d3> in <module>()
----> 1 y = x.format(one="one")
KeyError: 'two'
I have a compound string with many keys that gets kept in a config file. For 8 different queries, they all use the same string, except 1 key is a different setting. I need to be able to substitute a key in that file to save the strings for later like:
"this string takes two like one and {two}"
How do I substitute one key at a time using format
?
Upvotes: 0
Views: 1208
Reputation: 9682
All great answers, I will start using this Template
package soon. Very disappointed in the default behavior here, not understanding why a string template requires passing all the keys each time, if there are 3 keys I can't see a logical reason you can't pass 1 or 2 (but I also don't know how compilers work)
Solved by using %s
for the items I'm immediately substituting in the config file, and {key}
for the keys I replace later upon execution of the flask server
In [1]: issue = "Python3 string {item} are somewhat defective: %s"
In [2]: preformatted_issue = issue % 'true'
In [3]: preformatted_issue
Out[3]: 'Python3 string {item} are somewhat defective: true'
In [4]: result = preformatted_issue.format(item='templates')
In [5]: result
Out[5]: 'Python3 string templates are somewhat defective: true'
Upvotes: 0
Reputation: 46583
If placeholders in your string don't have any format specifications, in Python 3 you can use str.format_map
and provide a mapping, returning the field name for missing fields:
class Default(dict):
def __missing__(self, key):
return '{' + key + '}'
In [6]: x = "this string takes two like {one} and {two}"
In [7]: x.format_map(Default(one=1))
Out[7]: 'this string takes two like 1 and {two}'
If you do have format specifications, you'll have to subclass string.Formatter
and override some methods, or switch to a different formatting method, like string.Template
.
Upvotes: 3
Reputation: 46901
you can escape the interpolation of {two}
by doubling the curly brackets:
x = "this string takes two like {one} and {{two}}"
y = x.format(one=1)
z = y.format(two=2)
print(z) # this string takes two like 1 and 2
a different way to go are template strings:
from string import Template
t = Template('this string takes two like $one and $two')
y = t.safe_substitute(one=1)
print(y) # this string takes two like 1 and $two
z = Template(y).safe_substitute(two=2)
print(z) # this string takes two like 1 and 2
(this answer was before mine for the template strings....)
Upvotes: 2
Reputation: 78564
I think string.Template
does what you want:
from string import Template
s = "this string takes two like $one and $two"
s = Template(s).safe_substitute(one=1)
print(s)
# this string takes two like 1 and $two
s = Template(s).safe_substitute(two=2)
print(s)
# this string takes two like 1 and 2
Upvotes: 3
Reputation: 6891
You can replace {two}
by {two}
to enable further replacement later:
y = x.format(one="one", two="{two}")
This easily extends in multiple replacement passages, but it requires that you give all keys, in each iteration.
Upvotes: 1