How to split the definition of a long string over multiple lines?

1,628,546

Solution 1

Are you talking about multi-line strings? Easy, use triple quotes to start and end them.

s = """ this is a very
        long string if I had the
        energy to type more and more ..."""

You can use single quotes too (3 of them of course at start and end) and treat the resulting string s just like any other string.

NOTE: Just as with any string, anything between the starting and ending quotes becomes part of the string, so this example has a leading blank (as pointed out by @root45). This string will also contain both blanks and newlines.

I.e.,:

' this is a very\n        long string if I had the\n        energy to type more and more ...'

Finally, one can also construct long lines in Python like this:

 s = ("this is a very"
      "long string too"
      "for sure ..."
     )

which will not include any extra blanks or newlines (this is a deliberate example showing what the effect of skipping blanks will result in):

'this is a verylong string toofor sure ...'

No commas required, simply place the strings to be joined together into a pair of parenthesis and be sure to account for any needed blanks and newlines.

Solution 2

If you don't want a multiline string, but just have a long single line string, you can use parentheses. Just make sure you don't include commas between the string segments (then it will be a tuple).

query = ('SELECT   action.descr as "action", '
         'role.id as role_id,'
         'role.descr as role'
         ' FROM '
         'public.role_action_def,'
         'public.role,'
         'public.record_def, '
         'public.action'
         ' WHERE role.id = role_action_def.role_id AND'
         ' record_def.id = role_action_def.def_id AND'
         ' action.id = role_action_def.action_id AND'
         ' role_action_def.account_id = '+account_id+' AND'
         ' record_def.account_id='+account_id+' AND'
         ' def_id='+def_id)

In a SQL statement like what you're constructing, multiline strings would also be fine. But if the extra white space a multiline string would contain would be a problem, then this would be a good way to achieve what you want.

As noted in the comments, concatenating SQL queries in this way is a SQL injection security risk waiting to happen, so use your database's parameterized queries feature to prevent this. However, I'm leaving the answer as-is otherwise as it directly answers the question asked.

Solution 3

Breaking lines by \ works for me. Here is an example:

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"

Solution 4

I found myself happy with this one:

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')

Solution 5

I find that when building long strings, you are usually doing something like building an SQL query, in which case this is best:

query = ' '.join((  # Note double parentheses. join() takes an iterable
    "SELECT foo",
    "FROM bar",
    "WHERE baz",
))

What Levon suggested is good, but it might be vulnerable to mistakes:

query = (
    "SELECT foo"
    "FROM bar"
    "WHERE baz"
)

query == "SELECT fooFROM barWHERE baz"  # Probably not what you want
Share:
1,628,546
Pablo Mescher
Author by

Pablo Mescher

I'm a passionate web full stack developer with strong JS background. I am always looking to learn new ways of doing what I love (writing programs) and strive to learn the "why"s instead of the "how"s. Also, if I know the answer I'm more than happy to share it. Knowledge should be universal. This doesn't stop me from ranting from time to time about the "best" way of doing something, but I also try to listen and be open to challenge my own preconceptions in every field. btc address: 13bFKZ4DfSzrS28vYG1C2W8w1rhaBNkAWd

Updated on May 07, 2022

Comments

  • Pablo Mescher
    Pablo Mescher about 2 years

    I have a very long query. I would like to split it in several lines in Python. A way to do it in JavaScript would be using several sentences and joining them with a + operator (I know, maybe it's not the most efficient way to do it, but I'm not really concerned about performance in this stage, just code readability). Example:

    var long_string = 'some text not important. just garbage to' +
                          'illustrate my example';
    

    I tried doing something similar in Python, but it didn't work, so I used \ to split the long string. However, I'm not sure if this is the only/best/pythonicest way of doing it. It looks awkward. Actual code:

        query = 'SELECT action.descr as "action", '\
            'role.id as role_id,'\
            'role.descr as role'\
            'FROM '\
            'public.role_action_def,'\
            'public.role,'\
            'public.record_def, '\
            'public.action'\
            'WHERE role.id = role_action_def.role_id AND'\
            'record_def.id = role_action_def.def_id AND'\
            'action.id = role_action_def.action_id AND'\
            'role_action_def.account_id = ' + account_id + ' AND'\
            'record_def.account_id=' + account_id + ' AND'\
            'def_id=' + def_id
    
    • John Gaines Jr.
      John Gaines Jr. almost 12 years
      Since your example looks like a SQL block just waiting for an injection attack, another suggestion is to look into a higher level SQL library like SQLAlchemy or something to steer clear of hacking together raw SQL like this. (Perhaps off-topic, but you did ask for "Any suggestions". ;)
    • Bob Stein
      Bob Stein over 9 years
      This is "Pythonic way to create multi-line code for a long string" To create a string containing newlines see textwrap.dedent.
    • Pablo Mescher
      Pablo Mescher over 6 years
      @cezar I wrote this question more than five years ago, but I remember it arose from not knowing how to properly put the long sql query in several lines. I agree I was doing stupid things with that long string, but that was not my question and I wasn't smart enough to look for a better example to illustrate it that didn't include some sql injection concerns.
    • bugmenot123
      bugmenot123 about 5 years
      @cezar no, this is not a XY problem, the query would be best formatted in multiple lines in any case. SQLi is unrelated to the question at hand. Big bold warnings however are totally justified :)
    • Shay
      Shay over 4 years
      I wrote a small package for this. Example here: stackoverflow.com/a/56940938/1842491
    • Stevoisiak
      Stevoisiak about 2 years
  • Ashwini Chaudhary
    Ashwini Chaudhary almost 12 years
    @Pablo you can even add comments after the ,
  • kon psych
    kon psych almost 10 years
    @200OK you mean after '?
  • kon psych
    kon psych almost 10 years
    Another way to format this string would be to add .format(...) after the closing parenthesis. % formating notation must work too but I haven't tried it
  • Marco Sulla
    Marco Sulla almost 10 years
    I prefer to use explicitly the "+" operator for the second method. Not much an hassle and improves readability.
  • Joshua Taylor
    Joshua Taylor over 9 years
    @LucasMalor The adjacent strings are a compile-time concatenation. Doesn't using the + operator make the concatenation happen at runtime?
  • Bob Stein
    Bob Stein over 9 years
    +1 Relieves code-reviewer from having to assiduously check the right end of every line for inadequate whitespace. The OP committed this mistake several times, as noted by @KarolyHorvath.
  • m3nda
    m3nda almost 9 years
    "recursive function" is not that called lambda?
  • yoyo
    yoyo almost 9 years
    Note that each line must end with a string constant, so ' foo '+variable won't work, but ' foo '+variable+'' will.
  • Khanh Hua
    Khanh Hua over 8 years
    I would prefer either the triple quote notation or wrapping inside () to the \ character
  • neverendingqs
    neverendingqs almost 8 years
    For reference, here are the official docs to this phenomenon: docs.python.org/2/reference/… (python 2) and docs.python.org/3/reference/… (python 3)
  • Dani
    Dani over 7 years
    How about + stuff? To mix variables and strings. How do you indent that?
  • Umbrella
    Umbrella over 7 years
    When reviewing multiline strings coded in similar fashion, I require adequate whitespace on the left end of every line for easy confirmation.
  • Scott Prive
    Scott Prive over 7 years
    Your example is good, but I wish it had included demonstrating how to safely and securely embed variable data into the query. Both the OP and @jessee example code show how NOT to do it correctly (they're invitations to SQL attacks). See also: dev.mysql.com/doc/connector-python/en/…
  • Scott Prive
    Scott Prive over 7 years
    This example is an open door to SQL injection attacks. Please, no one use this on any public-facing application. See the MySQL docs for how to use 'placeholders': dev.mysql.com/doc/connector-python/en/…
  • Charles D Pantoga
    Charles D Pantoga over 7 years
    @BobStein-VisiBone Code reviews should not be about syntax errors or small bugs like this, they should be about substance. If somebody is putting code up for review that has syntax errors (and thus won't run either at all or in certain situations) then something is seriously wrong. It's not hard to run lint before you commit. If the person hasn't noticed their program doesn't run correctly because they made such an obvious mistake, they shouldn't be committing.
  • Bob Stein
    Bob Stein over 7 years
    Agreed @CharlesAddis, code reviews should come after automated methods, e.g. lint, syntax highlighting, etc. However some white-space-missing bugs may not be caught that way. Avail yourself of all reasonable advantages in guarding against bugs, I suggest.
  • xjcl
    xjcl about 7 years
    Disagree. What if the first line ("string = ...") is heavily indented? One would have to de-dent the following lines to zero indentation, which looks ugly in the middle of an otherwise indented block.
  • Eero Aaltonen
    Eero Aaltonen about 7 years
    Well, the majority of my lengthy strings occur at the module level, where this fits nicely. In your case though this would obviously not be the best solution.
  • Eduardo Lucio
    Eduardo Lucio almost 7 years
    I like this approach because it privileges reading. In cases where we have long strings there is no way... Depending on the level of indentation you are in and still limited to 80 characters per line... Well... No need to say anything else. In my view the python style guides are still very vague. Thanks!
  • Ayush Sharma
    Ayush Sharma almost 7 years
    What about string interpolation? If I want to use variables within this string, how would that work?
  • kuanb
    kuanb over 6 years
    How would an f-string work if I wanted to log the result of a multi-line string and not have the left-side tabs/spaces shown?
  • Corey Goldberg
    Corey Goldberg over 6 years
    you can use textwrap.dedent to remove unwanted leading whitespace. docs.python.org/3/library/textwrap.html#textwrap.dedent
  • Chris L
    Chris L over 6 years
    @JoshuaTaylor Whether you use implicit (adjacent) concatenation or use explicit concatenation with the + operator, either results in a compile-time concatenated string literal constant. It doesn't make any difference. In fact, you also get a compile-time string literal when you use the * operator with a string literal and an integer literal.
  • Alfe
    Alfe over 6 years
    I strongly advise to put the spaces at the beginning of the following lines instead of at the ending of the followed lines. This way an accidentally missing one is way more obvious (and thus is less likely to happen).
  • Ben
    Ben about 6 years
    Note, I haven't tested this, but you can probably avoid the question mark confusion by replacing them with "{0} {1} {2}" in the relevant places and then changing the last line to cursor.execute(query.format(vars)). That should take care of your only "con" (I hope).
  • Faheel
    Faheel about 6 years
    Yes, using format would be nice but I'm not sure whether the query string formatted that way would be safe from SQL injection.
  • Ben
    Ben about 6 years
    Yeah, that's a fair point and it could certainly get a bit tricky. Perhaps testing it on something entirely expendable would be wise ... no doubt a Comp. Sci. undergrad will wander past soon enough. ;)
  • bjd2385
    bjd2385 almost 6 years
    Look into Python's textwrap.dedent function, which is in the standard library, it has the functionality you need.
  • umbreonben
    umbreonben over 5 years
    He didn't ask for newlines in the string, bad answer.
  • Patrick Mevzek
    Patrick Mevzek over 5 years
    @Ben if you do cursor.execute(query.format(vars)) you do not profit from prepared statements anymore so you are vulnerable to many kind of problems, starting with the fact that if the parameters are not just numbers you need to double quote them in the SQL query.
  • jpmc26
    jpmc26 over 5 years
    @Crossfit_and_Beer They're called query parameters, and the queries that have them are called paramterized queries. And every major relational DBMS supports them.
  • Alexander
    Alexander over 5 years
    Why wouldn't you at least use an array literal?
  • Trenton
    Trenton over 5 years
    Still vulnerable to SQL injection
  • paone
    paone over 5 years
    Arrays are represented by class list. check out another discussion regarding the array literals
  • ShadowRanger
    ShadowRanger over 5 years
    Note: inspect.cleandoc is slightly nicer than textwrap.dedent, as it doesn't require the first line to be empty with a line continuation character at the end.
  • Christopher Bruns
    Christopher Bruns over 5 years
    @ShadowRanger Wow I never used cleandoc before. I updated my answer and will in future use inspect.cleandoc for this.
  • zyy
    zyy about 5 years
    I like the black slash that prevents auto new line, thanks so much!
  • Petro
    Petro over 4 years
    I suppose this works, but you should think about performance and readability...
  • cezar
    cezar over 4 years
    This best answers the title of the question - it is indeed the most Pythonic way to create a multi-line string. There is still an issue with SQL injection, but that wasn't a core part of the question.
  • frmbelz
    frmbelz over 4 years
    Also works with variables at the end of lines longStr = "account: " + account_id + \ ...
  • ShadowRanger
    ShadowRanger over 4 years
    @bjd2385: inspect.cleandoc is slightly nicer (less finicky about whether or not text appears on the same line as the open quotes, doesn't require explicit line continuation characters).
  • alper
    alper almost 4 years
    I am getting following error: the backslash is redundant between brackets when I wrote in inside print()
  • alper
    alper almost 4 years
    This would be so ugly if it is used under a module, I have to as also .replace('\t','')
  • Arthur Tarasov
    Arthur Tarasov almost 4 years
    @Alfe No need to worry about missing \'s anymore. VScode will have a heart attack if I miss one
  • Alfe
    Alfe almost 4 years
    @ArthurTarasov I didn't worry about the backslashes. My comment what about the spaces within the string. In the answer they are at the end of the first, second, and third line, every time at a different column, hence a missing one can easily be overlooked. I recommend to put them instead at the beginning of the second, third, and fourth line, every time at column 1 of the string, hence neatly above each other so that a missing one is quite obvious and thus unlikely to happen.
  • Joseph Astrahan
    Joseph Astrahan over 3 years
    This worked great for me! Gets rid of the spaces that are added from the editor during the ''' quote process!
  • Keto
    Keto over 3 years
    If you care about code-folding, this would break it in most editors.
  • Christopher Bruns
    Christopher Bruns over 3 years
    That back slash would be unnecessary if you used inspect.cleandoc instead of textwrap.dedent.
  • Blisterpeanuts
    Blisterpeanuts over 3 years
    Excellent answer. This solved my problem as well -- I have double quotes inside a multi-line string and they are automatically handled correctly.
  • Lou
    Lou over 3 years
    Don't you need commas or + in the example with parentheses?
  • Peter Mortensen
    Peter Mortensen about 3 years
  • jackblk
    jackblk about 3 years
    Although it looks really nice, I think this approach will be vulnerable to SQL injection. Sadly f-string is not good with SQL queries. From other comments, it is better to use cursor.execute instead dev.mysql.com/doc/connector-python/en/…
  • Timo
    Timo about 3 years
    Using f strings here seems more natural and easy.
  • echefede
    echefede about 3 years
    The + operator will give you problems when using string methods.
  • ss7
    ss7 almost 3 years
    Note: The second method only works when the string is enclosed in ( ). Otherwise a backslash is needed at the end of each line.
  • Chris Collett
    Chris Collett over 2 years
    Avoid using backslashes to break up long lines of code. It reduces clarity, makes refactoring more painful, and avoids the root of the problem (you don't know of a better way making your code fit within 79 characters).
  • chepner
    chepner over 2 years
    This is criminally undervoted.
  • Ideogram
    Ideogram about 2 years
    Added benefit is that you can quickly out-comment lines.
  • liakoyras
    liakoyras about 2 years
    Note that this does not work very well with indented code (aesthetically).