237

How do I wrap long lines in Python without sacrificing indentation?

For example:

def fun():
    print '{0} Here is a really long sentence with {1}'.format(3, 5)

Suppose this goes over the 79 character recommended limit. The way I read it, here is how to indent it:

def fun():
    print '{0} Here is a really long \
sentence with {1}'.format(3, 5)

However, with this approach, the indentation of the continued line matches the indentation of the fun(). This looks kinda ugly. If someone was to go through my code, it would look bad to have uneven indentation because of this print statement.

How do I indent lines like this effectively without sacrificing code readability?

c32hedge
  • 785
  • 10
  • 19
user225312
  • 126,773
  • 69
  • 172
  • 181
  • 1
    Also take a look at this related question - http://stackoverflow.com/questions/53162/how-can-i-do-a-line-break-line-continuation-in-python – Pierz Oct 02 '13 at 14:03

6 Answers6

315
def fun():
    print(('{0} Here is a really long '
           'sentence with {1}').format(3, 5))

Adjacent string literals are concatenated at compile time, just as in C. http://docs.python.org/reference/lexical_analysis.html#string-literal-concatenation is a good place to start for more info.

Darwyn
  • 4,696
  • 3
  • 25
  • 26
pv2b
  • 3,359
  • 1
  • 15
  • 3
  • 33
    Actually, the "\" is redundant and can be omitted. – Daniel Reis Jan 07 '13 at 17:19
  • 5
    @DanielReis I'm not sure that's true of all platforms or Python distributions. I received some output from a user where everything after the first line was not printed. My code was like the above, sans backslash. – BHSPitMonkey Jul 01 '13 at 18:49
  • 7
    Unicode strings need the backslash in python 2.x – gypaetus Jul 07 '13 at 22:30
  • 5
    Within parentheses line continuation is implicit, so a `+` instead suffices. Note that avoiding Parentheses hinders portability to Python 3.x, imagine a code whose only need for `2to3` are `print` statements, but would otherwise w/o requiring any conversion. – 0 _ Aug 10 '13 at 08:17
  • 1
    This won't work for python 3, compared to [this alternative](http://stackoverflow.com/a/18160132/1959808). – 0 _ Aug 13 '14 at 20:10
  • this syntax is misleading. as much as i'd love to have that identation, if the above is used you will get `IndentationError: unexpected indent`. Python expects you to have all the pieces of the string starting on the very same identation as the variable being assigned. – gcb Sep 30 '14 at 01:36
  • You have to use the backslash when inside the interpreter though – Tasdik Rahman Mar 18 '16 at 16:19
  • 1
    @DanielReis: the "\" is not redundant. You get an `IndentationError: unexpected indent` otherwise. Please remove your comment! – Robert Siemer Apr 13 '16 at 16:16
  • 2
    @MigueldeVal-Borro, your comment reason is wrong: the backslash is needed because the line break is not in a pair of parenthesis (or brackets, ...). I.e. byte strings need the backslash, too! – Robert Siemer Apr 13 '16 at 16:22
  • now that f-strings are a thing and python 2.7 is dead and buried, it's probably a good idea to show the modern syntax first (with the historical answer second for folks who for some unfortunate reason are forced into maintaining 2.7 code) – Mike 'Pomax' Kamermans Jan 13 '21 at 21:24
  • How does this work for bytes? I have something like this
    
    longLine = b'Line1\r\n'
    'Line2\r\n'
    'Line3\r\n'
    print( longLine )
    
    
    $ python3 test.py
    b'Line1\r\n'
    – Mister Rose Feb 25 '21 at 17:35
87

Using concatenation of adjacent string literals, together with formatted string literals is the way to go:

x = 2
sep = 2 * '\n'
print(
    'This message is so long that it requires '
    f'more than {x} lines.{sep}'
    'And more lines may be needed.')

This approach complies with PEP 8 and allows better use of space.

No + operators needed, no backslashes for line continuation, no irregularities of indentation, no error-prone += to an accumulator string variable (which can be mistyped as =, resulting in a silent error), no stray parenthesis hanging below the print (the arguments are placed in their own level of indentation, and the next element at the indentation level of print is the next statement).

Starting the strings on the line below the line that contains the print( reduces indentation, and is more readable. Readability stems from both print( standing out, by being on its own line, and by the uniform alignment of consecutive statements of this form.

The reduction in indentation from this approach becomes more evident when raising exceptions:

raise ModuleNotFoundError(
    'aaaaaaaaaaaaaaaaaaaaaaaa'
    'aaaaaaaaaaaaaaaaaaaaaaaa'
    f'aaaaa {x} aaaaa')

Regarding formatted string literals (signified by the prefix "f", as in f'...'), raw strings can be formatted string literals, by combining the prefixes "r" and "f":

rf'This is a formatted raw string, {sep}here is a backslash \.'

Note that raw strings are necessary for including literal backslashes without writing \\. Otherwise, in a future CPython version, a SyntaxError will be raised. As of Python 3.9, a DeprecationWarning is raised:

python -X dev -c '"\q"'

outputs:

<string>:1: DeprecationWarning: invalid escape sequence \q

The replacements are very readable. In particular, this approach makes writing code that generates code or mathematical formulas a very pleasant task.

Rarely, the method str.format may be suitable, due to what substitutions are needed. It can be used as follows:

print((
    'This message is so long that it requires '
    'more than {x} lines.{sep}'
    'And more lines may be needed.'
    ).format(x=x, sep=sep))
0 _
  • 10,524
  • 11
  • 77
  • 109
  • Does it have any downsides (first approach)? Because to me it is way better than others. – antonavy Dec 02 '15 at 19:16
  • My experience with it until now says that it doesn't have any downsides. It's an all-weather, very readable pattern that can be used everywhere, from messages to compiler backends. – 0 _ Dec 02 '15 at 20:13
  • Will the PEP 8 solution cause line breaks to be entered if I intend to put this text in a `.csv` file or other output file format besides the terminal? My fear is that I'll numerous lines when I expected only 1. – Chris Jun 28 '16 at 13:55
  • There are no newlines other than the explicit `\n` introduced by `sep` (just define `sep` differently). The strings are simply concatenated. – 0 _ Jun 28 '16 at 21:40
23

You could use the following code where indentation doesn't matter:

>>> def fun():
        return ('{0} Here is a really long'
        ' sentence with {1}').format(3, 5)

You just need to enclose string in the parentheses.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
  • 4
    Warning for python rookies: this code is not PEP8 compliant and ought not to be indented this way. – glarrain Jul 19 '13 at 17:48
20

You can use the fact that Python concatenates string literals which appear adjacent to each other:

>>> def fun():
...     print '{0} Here is a really long ' \
...           'sentence with {1}'.format(3, 5)
Chris B.
  • 85,731
  • 25
  • 98
  • 139
10

I'd probably split the long statement up into multiple shorter statements so that the program logic is separated from the definition of the long string:

>>> def fun():
...     format_string = '{0} Here is a really long ' \
...                     'sentence with {1}'
...     print format_string.format(3, 5)

If the string is only just too long and you choose a short variable name then by doing this you might even avoid having to split the string:

>>> def fun():
...     s = '{0} Here is a really long sentence with {1}'
...     print s.format(3, 5)
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • Yes I had considered this approach also. It is indeed a viable one. – user225312 Jul 27 '10 at 17:44
  • Actually missing out the `+` would work here too, as pointed out by the other answers and would be an improvement to my answer. The difference in my answer from the others is that I'm not trying to do everything in one statement. I think it helps readability to split long statements up into multiple shorter ones. – Mark Byers Jul 27 '10 at 17:45
  • The only downside to this would be I have to declare a separate string for this. I have no problem with that but I guess the parenthesis approach should work, imo. – user225312 Jul 27 '10 at 17:47
  • Since you already accepted, I updated my answer to include the idea from the accepted answer. – Mark Byers Jul 27 '10 at 18:00
  • Yes I had seriously considered your approach but then I decided to ask here. Since print and format itself take space, this works. – user225312 Jul 27 '10 at 18:08
  • Well for some reason this is the lowest voted answer so maybe it's not so good as I thought... never mind. I'll leave it anyway as I think it might be useful to someone. – Mark Byers Jul 27 '10 at 18:21
6

I'm surprised no one mentioned the implicit style above. My preference is to use parens to wrap the string while lining the string lines up visually. Personally I think this looks cleaner and more compact than starting the beginning of the string on a tabbed new line.

Note that these parens are not part of a method call — they're only implicit string literal concatenation.

Python 2:

def fun():
    print ('{0} Here is a really '
           'long sentence with {1}').format(3, 5)

Python 3 (with parens for print function):

def fun():
    print(('{0} Here is a really '
           'long sentence with {1}').format(3, 5))

Personally I think it's cleanest to separate concatenating the long string literal from printing it:

def fun():
    s = ('{0} Here is a really '
         'long sentence with {1}').format(3, 5)
    print(s)
Taylor D. Edmiston
  • 12,088
  • 6
  • 56
  • 76