49

I have this api call.

payload = "{\\"weight\\":{\\"value\\":\\"85.00\\",\\"unit\":\\"kg\\"},\\"height\\":{\\"value\\":\\"170.00\\",\\"unit\\":\\"cm\\"},\\"sex\\":\\"m\\",\\"age\\":\\"24\\",\\"waist\\":\\"34.00\\",\\"hip\\":\\"40.00\\"}"

I want to use a f string to change those values but I get a syntax error saying I can't use backslash for f strings. What can I do?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
user15975293
  • 515
  • 1
  • 4
  • 3
  • 4
    Did you remember to double your `{` and `}` literal characters to avoid having them interpreted as formatted insertions? You need to provide the *broken* code, and ideally the traceback; working code plus "If I change it to something I'm not showing it breaks" is not enough for us to help with. We need a [MCVE]. – ShadowRanger May 25 '21 at 00:32
  • 1
    Well, you can start by putting a `f` before the first `"`. – Have a nice day May 25 '21 at 00:33
  • 1
    Does this answer your question? [How can I print literal curly-brace characters in a string and also use .format on it?](https://stackoverflow.com/questions/5466451/how-can-i-print-literal-curly-brace-characters-in-a-string-and-also-use-format) – Gabriel Cretin Dec 10 '21 at 17:06

2 Answers2

84

This is currently a limitation of f-strings in python. Backslashes aren't allowed in them at all (see https://mail.python.org/pipermail/python-dev/2016-August/145979.html) Update: As of 2023, any version of Python that isn't EOL supports the backslash character within the string portion of the f-string (for example, f"This \ is allowed"), however support for backslash characters within the brace substitution is still disallowed (for example, f"This {'\\'} is not allowed".

Option 1

The best way would be to instead use use str.format() to accomplish this, per https://docs.python.org/3/library/stdtypes.html#str.format

Option 2

If you're super keen on using backslashes, you could do something like this:

backslash_char = "\\"
my_string = f"{backslash_char}foo{bar}"

But that's probably not the best way to make your code readable to other people.

Option 3

If you're absolutely certain you'll never use a particular character, you could also put in that character as a placeholder, something like

my_string = f"{}foo{bar}".replace("", "\\")

But that's also super workaround-y. And it's a great way to introduce bugs down the road, if you ever get an input with that char in it.

Option 4

As mentioned in the comments to this answer, another option would be to do chr(92) inside some curlies, as below:

my_string = f"This is a backslash: {chr(92)}"
AmphotericLewisAcid
  • 1,824
  • 9
  • 26
  • 8
    You could also use `chr(92)` (92 being the ASCII code for backslash) – Jay Dadhania Aug 06 '21 at 23:44
  • 2
    Actually you can double the "{" or “}" you want to really print like `print(f"really show this {{")` – Gabriel Cretin Dec 10 '21 at 17:04
  • 19
    `chr(10)` if you are trying to get a new line (`\n`) in a f-string – run_the_race May 04 '22 at 13:23
  • 2
    This answer is incorrect for python 3.10. The limitation is just on backslash sequences in the *expression* part of f-strings, as the error message states. – user1254127 Sep 22 '22 at 09:12
  • 1
    I'm surprised this limitation is intentional. There is no technical problem behind it, it simply exists "to avoid convoluted code". I don't think inserting more `{}` referencing local strings is less convoluted than escape sequences. – Xeverous Nov 22 '22 at 22:52
  • 1
    **This answer is wrong**. It has always been possible to use backslashes within the f-string itself, just not **within the brace-substitution parts**. Most likely, OP was running into a problem due to the desired output containing literal `{` and `}` characters, which need to be escaped. The linked discussion took place in planning phases, before the feature was implemented. – Karl Knechtel Jan 22 '23 at 03:52
  • **This answer is still correct for Python 3.10 and 3.11.** I just tried this on both, and backslashes are still disallowed in the brace substitution. That said, thanks for catching the out of date reference to the mailing list! I've updated the first sentence to reflect the current state of the language, but the entirety of the answer focuses on how to include backslashes as part of the brace substitution (did only the first line of the answer linking to the mailing list load? :P). The only way OP gets their error message is by trying to put a backslash in the brace substitution. – AmphotericLewisAcid Jul 27 '23 at 02:25
  • @AmphotericLewisAcid That solved my problem `.str.extract(pat=f"^({'{0}|'.join(list_elements)})".format("\."))` , from this original not working one `.str.extract(pat=f"^({'\.|'.join(list_elements)})")` – Lod Aug 14 '23 at 07:41
3
class data(object):
    _weight = 85.00
    _height = 170.00
    _sex = 'm'
    _age = '24'
    _waist = 34.0
    _hip = 40.0

payload = f'\
{{\
    "weight": {{\
        "value": "{data._weight}",\
        "unit": "kg"\
    }},\
    "height": {{\
        "value": "{data._height}",\
        "unit": "cm"\
    }},\
    "sex": "{data._sex}",\
    "age": "{data._age}",\
    "waist": "{data._waist}",\
    "hip": "{data._hip}"\
}}'

print(payload)

Result:

C:\>python.exe test.py
{ "weight": { "value": "85.00", "unit": "kg" }, "height": { "value": "170.00", "unit": "cm" }, "sex": "m", "age": "24", "waist": "34.0", "hip": "40.0" }

Result via 'jq':   (check here for info on 'jq')

C:\>python.exe test.py | jq .
{
  "weight": {
    "value": "85.00",
    "unit": "kg"
  },
  "height": {
    "value": "170.00",
    "unit": "cm"
  },
  "sex": "m",
  "age": "24",
  "waist": "34.0",
  "hip": "40.0"
}
Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108