Proper indentation for Python multiline strings
You probably want to line up with the """
def foo():
string = """line one
line two
line three"""
Since the newlines and spaces are included in the string itself, you will have to postprocess it. If you don't want to do that and you have a whole lot of text, you might want to store it separately in a text file. If a text file does not work well for your application and you don't want to postprocess, I'd probably go with
def foo():
string = ("this is an "
"implicitly joined "
"string")
If you want to postprocess a multiline string to trim out the parts you don't need, you should consider the textwrap
module or the technique for postprocessing docstrings presented in PEP 257:
def trim(docstring):
if not docstring:
return ''
# Convert tabs to spaces (following the normal Python rules)
# and split into a list of lines:
lines = docstring.expandtabs().splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxint
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Remove indentation (first line is special):
trimmed = [lines[0].strip()]
if indent < sys.maxint:
for line in lines[1:]:
trimmed.append(line[indent:].rstrip())
# Strip off trailing and leading blank lines:
while trimmed and not trimmed[-1]:
trimmed.pop()
while trimmed and not trimmed[0]:
trimmed.pop(0)
# Return a single string:
return '\n'.join(trimmed)
The textwrap.dedent
function allows one to start with correct indentation in the source, and then strip it from the text before use.
The trade-off, as noted by some others, is that this is an extra function call on the literal; take this into account when deciding where to place these literals in your code.
import textwrap
def frobnicate(param):
""" Frobnicate the scrognate param.
The Weebly-Ruckford algorithm is employed to frobnicate
the scrognate to within an inch of its life.
"""
prepare_the_comfy_chair(param)
log_message = textwrap.dedent("""\
Prepare to frobnicate:
Here it comes...
Any moment now.
And: Frobnicate!""")
weebly(param, log_message)
ruckford(param)
The trailing \
in the log message literal is to ensure that line break isn't in the literal; that way, the literal doesn't start with a blank line, and instead starts with the next full line.
The return value from textwrap.dedent
is the input string with all common leading whitespace indentation removed on each line of the string. So the above log_message
value will be:
Prepare to frobnicate:
Here it comes...
Any moment now.
And: Frobnicate!
Use inspect.cleandoc
like so:
def method():
string = inspect.cleandoc("""
line one
line two
line three""")
Relative indentation will be maintained as expected. As commented below, if you want to keep preceding empty lines, use textwrap.dedent
. However that also keeps the first line break.
Note: It's good practice to indent logical blocks of code under its related context to clarify the structure. E.g. the multi-line string belonging to the variable
string
.