Python Part I · Module 4 · Strings
Quotes, Escapes and Multi-Line Text
Before you can do anything to text you have to be able to write it down, and text does not always cooperate. Sometimes it contains an apostrophe. Sometimes it contains a quotation mark. Sometimes it needs a tab between two fields, or a line break in the middle, or a Windows path full of backslashes — and that last one silently produces the wrong string for more beginners than any other single mistake in Python. This chapter works through each of those needs in turn, introduces escape sequences only when a piece of text actually requires one, and finishes with triple quotes, which let you write a block of text across several lines exactly as it should appear.
Foundation12 min readPythonPart IFundamentalsStringsEscapes
Part I · Module 4 · Chapter 4.2 · Quotes, Escapes and Multi-Line Text
1. Two Quote Characters, and Why
Chapter 2.9 said a string is written between matching quotes, and that Python accepts either kind. Both of these are ordinary strings and there is no difference at all between them as values:
path = "runs/axi_smoke/sim.log"
name = 'axi_smoke'
print(path)
print(name)runs/axi_smoke/sim.log
axi_smokeSo why does Python offer two? Because text sometimes contains a quote character of its own, and the quote marking the boundary cannot also be a character inside.
Here is the problem in its smallest form. This text contains an apostrophe:
msg = "the tool's report"
print(msg)the tool's reportThat works because the boundaries are double quotes, so the single quote inside is just a character. Had we written 'the tool's report', Python would have read the string as ending at tool, and the rest would be a syntax error.
The mirror case is text containing a double quote:
says = 'he said "PASS"'
print(says)he said "PASS"Single quotes on the outside, double quotes safely inside.
Many teams pick one style — usually double quotes — and use it by default, switching to the other only when the text demands it. That is a readability convention rather than a language rule, and it is a good habit: it means the exceptions stand out.
2. When the Text Contains Both
The rule above runs out when a piece of text contains both kinds of quote. Neither boundary character is safe, and this is the first time you genuinely need a new tool:
both = "it said \"the tool's done\""
print(both)it said "the tool's done"The interesting part is \". A backslash in front of a quote tells Python: this quote is a character in the text, not the end of the text. The backslash itself does not appear in the value — look at the output, there is no backslash in it.
A backslash used this way is called an escape. It escapes the character that follows from its usual meaning.
This is worth stating carefully, because it is the idea the whole rest of the chapter depends on:
3. The Newline: One Character, Not Two
The most-used escape is not for quotes. It is \n, which means a line break.
print("first\nsecond")first
secondOne string, printed once, and the output has two lines. The \n in the middle is the line break.
Now the point that beginners routinely get wrong. Ask how long that string is — how many characters it contains. Use len(), which Chapter 4.6 teaches properly; here it is just evidence:
print(len("a\nb"))3Three. The characters are a, a newline, and b. The \n you typed is two keystrokes but it is one character in the value.
Compare it against a string that really does contain a backslash followed by an n. To get that you escape the backslash itself, by doubling it:
print(len("a\\nb"))
print("a\\nb")4
a\nbFour characters this time — a, backslash, n, b — and printing it shows a visible backslash. The first string is a line break; the second describes one.
The tab escape works identically, and is useful when text needs a column break:
print("name\tstatus")name status4. The Backslash Problem
Here is the mistake this chapter most needs to prevent. Somebody writes a Windows-style path:
p = "C:\temp\data"
print(p)
print(len(p))Python does two things you did not ask for:
bad.py:1: SyntaxWarning: invalid escape sequence '\d'
p = "C:\temp\data"
C: emp\data
11Read that carefully, because two different failures are visible at once.
\t was a valid escape, so Python used it. It silently became a tab. That is why the output shows C: then a gap then emp — the t of temp is gone, consumed into the tab. No warning, no error; the string is simply not the one intended.
\d is not a valid escape, so Python warned about it and left the backslash and the d alone. That is the SyntaxWarning line, and it is Python trying to tell you the author probably meant something else.
And the length is 11, not the 12 characters of the path as written — because two keystrokes became one tab.
There are two correct ways to write that path. Double every backslash, so each pair means one literal backslash:
q = "C:\\temp\\data"
print(q)
print(len(q))C:\temp\data
12Or prefix the string with r, which makes it a raw string:
r_path = r"C:\temp\data"
print(r_path)
print(len(r_path))C:\temp\data
12Both give the same 12-character value. You can check that directly:
print("C:\\temp\\data" == r"C:\temp\data")TrueOn Linux and macOS paths use forward slashes, which are not escapes and need none of this:
print("runs/axi_smoke/sim.log")runs/axi_smoke/sim.logThat is the real reason most Python you read uses forward slashes even on Windows, where they also work.
5. Broken on Purpose
Three failures worth meeting deliberately. Each was executed; the messages are exactly what Python prints.
Forgetting the closing quote.
name = "axi_smoke
print(name) File "bad.py", line 1
name = "axi_smoke
^
SyntaxError: unterminated string literal (detected at line 1)"Unterminated" means the string was opened and never closed. Note that Python points at the line where the string started and at the opening quote — it is telling you where the problem began, not where it noticed.
Using the same quote inside and outside.
says = "he said "PASS""
print(says) File "bad.py", line 1
says = "he said "PASS""
^^^^
SyntaxError: invalid syntaxPython read "he said " as a complete string, then found PASS sitting there with no operator in front of it, and stopped. The carets point at PASS, which is where it got confused rather than where the mistake is. The fix is either outer single quotes or escaped inner ones, from Sections 1 and 2.
Ending a raw string with a backslash.
d = r"runs\"
print(d) File "bad.py", line 1
d = r"runs\"
^
SyntaxError: unterminated string literal (detected at line 1); perhaps you escaped the end quote?That trailing hint — perhaps you escaped the end quote? — is Python being genuinely helpful, and it is the precise reason the callout above says a raw string cannot end in a backslash. To write a directory path ending in a separator, use "runs\\" instead.
6. Multi-Line Text With Triple Quotes
You can build multi-line text with \n, and for one break that is fine. For a block of text it becomes hard to read:
print("REGRESSION SUMMARY\nnightly\n3 tests")REGRESSION SUMMARY
nightly
3 testsPython offers a better way for this case: three quote characters open and close the string, and real line breaks inside it are kept.
banner = """REGRESSION SUMMARY
nightly
3 tests"""
print(banner)REGRESSION SUMMARY
nightly
3 testsThe text now looks in the source the way it looks in the output, which is the point. Three single quotes work identically:
print('''line one
line two''')line one
line twoTwo details decide whether the result is what you wanted.
The line breaks you can see are the line breaks you get. A triple-quoted string contains exactly the characters between the delimiters, newlines included:
print(len("""ab
cd"""))5Five: a, b, newline, c, d. There is no hidden extra character and no missing one.
A line break immediately after the opening delimiter is part of the text. This is the one that causes surprise:
banner = """
REGRESSION SUMMARY
nightly
"""
print(len(banner))28That string begins with a newline, because there is a line break right after """, and ends with one, because there is a line break before the closing """. Printing it produces a blank line above and below the text. If you do not want the leading break, start the text on the same line as the opening delimiter, as the first example did.
7. The Escapes Worth Knowing
Now that each has arrived for a reason, here they are together. This is a summary, not a list to memorise — four entries cover nearly everything you will write:
| You type | You get | Use it for |
|---|---|---|
\n | one newline character | a line break inside text |
\t | one tab character | separating fields in output |
\" or \' | one quote character | a quote inside a same-quoted string |
\\ | one backslash | Windows paths, or any literal backslash |
Everything in the left column is two keystrokes and one character.
8. Predict, Run, Observe
Predict all four numbers before reading on.
print(len("PASS"))
print(len("PA\nSS"))
print(len("PA\\nSS"))
print(len("PA\tSS"))The verified output:
4
5
6
5The first is plain. The second is 5 — four letters plus one newline. The third is 6, because \\ is one backslash and the n after it is an ordinary letter, giving P A \ n S S. The fourth is 5 again: one tab.
If you predicted 6 for the second, you counted \n as two characters. That is the assumption Section 3 exists to correct, and it will otherwise resurface in every indexing and slicing exercise in the next three chapters.
9. Exercises
Exercise 1 — choose the quotes. Write each of these as a Python string, using the quote style that needs no escape at all. Print each to confirm:
(a) it's running (b) status "PASS" (c) runs/axi/sim.log
Exercise 2 — both kinds. Write a string whose text is exactly: the log says "it's done". You will need at least one escape. Print it and check the output character for character.
Exercise 3 — predict the length. Without running anything, give the length of each, then verify:
(a) "" (b) "\n" (c) "\\" (d) "a\tb\tc" (e) "C:\\runs"
Exercise 4 — fix the path. This does not hold the path the author meant. Say what the value actually contains, and rewrite the line two different ways so that it holds C:\new\runs:
p = "C:\new\runs"Exercise 5 — a header block. Write a three-line banner using triple quotes, with no blank line above or below it when printed. Then move the opening text onto its own line and explain, in one sentence, what changed about the value.
Exercise 6 — read the error. A colleague reports that this line gives SyntaxError: invalid syntax with carets under sim. Explain what Python read before it got confused, and give the corrected line:
msg = "log is "sim.log" now"10. Summary
- Single and double quotes are interchangeable for the value. Choose whichever the text itself does not contain.
- When text contains both kinds of quote, escape the inner one with a backslash:
\"or\'. - An escape is two characters in the source that mean one character in the value. The backslash does not appear in the result.
"\n"is one character."\\n"is two. Getting this wrong mispredicts every length, index and slice.\tis one tab, useful for column breaks in output.- A backslash in a path is a trap.
"C:\temp"silently contains a tab, and an unrecognised escape such as\dproduces aSyntaxWarning. Double the backslashes or use a raw string. - A raw string keeps backslashes as backslashes — it does not disable escaping entirely, and it cannot end with a backslash.
- Forward slashes need no escaping and work on every platform, which is why most Python uses them.
- Triple quotes hold multi-line text literally, including the newline right after the opening delimiter if you leave one there.
You can now write down any text you need. The next chapter combines pieces of text into larger ones.
Where this fits
Part of the Python curriculum.
