string manipulation
multi-line string
text processing
Python programming
string splitting

How do I split a multi-line string into multiple lines?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Splitting a multi-line string seems simple until newline style, trailing blank lines, and exact delimiter behavior start to matter. In Python, the best default is usually splitlines(), but it is not identical to splitting on "\n". The correct choice depends on whether you want logical lines normalized across platforms or exact raw separator behavior preserved.

Use splitlines() for Logical Lines

splitlines() understands common newline conventions such as Unix \n, Windows \r\n, and older \r.

python
1text = "one\r\ntwo\nthree\rfour"
2lines = text.splitlines()
3
4print(lines)

Output:

python
['one', 'two', 'three', 'four']

That makes splitlines() the safest high-level choice when text may come from multiple operating systems or mixed sources.

You can also keep the newline characters if you need them:

python
text = "a\nb\n"
print(text.splitlines(keepends=True))

That is useful in editors, diff tooling, or formatting utilities where line endings themselves matter.

Use split("\n") for Exact Delimiter Behavior

If you split on a literal newline character, Python treats the input more mechanically.

python
text = "a\nb\n\n"
print(text.split("\n"))

Output:

python
['a', 'b', '', '']

This preserves trailing empty fields, which can be useful in some parsing scenarios. The downside is that it does not normalize \r\n automatically, so Windows input may leave trailing \r in each line.

python
text = "x\r\ny\r\n"
print(text.split("\n"))

That result includes '\r' unless you clean it up yourself.

Decide How to Handle Blank Lines

Blank lines can be meaningful or noise depending on the task. If you want to remove empty lines and trim surrounding whitespace, do it explicitly.

python
1text = "alpha\n\n beta \n"
2lines = [line.strip() for line in text.splitlines() if line.strip()]
3
4print(lines)

If position matters, preserve the empties instead:

python
text = "header\n\nbody"
for index, line in enumerate(text.splitlines()):
    print(index, repr(line))

The point is that line splitting and blank-line filtering are separate decisions.

Stream Files Instead of Splitting Huge Strings

If the source is a file, do not read the whole thing into memory just to split it unless you actually need the full text as one string.

python
1with open("application.log", "r", encoding="utf-8", newline="") as handle:
2    for raw_line in handle:
3        line = raw_line.rstrip("\r\n")
4        if "ERROR" in line:
5            print(line)

That approach is better for large logs or exports because memory use stays bounded.

If you already have a string but want file-like iteration, io.StringIO works well:

python
1import io
2
3text = "line1\nline2\nline3"
4
5for line in io.StringIO(text):
6    print(line.rstrip("\n"))

Decode Bytes Before Splitting

If the data starts as bytes, decode first and then split the resulting string.

python
1payload = b"alpha\r\nbeta\r\n"
2text = payload.decode("utf-8")
3
4print(text.splitlines())

Trying to reason about line structure before decoding is a good way to hide an encoding bug inside a parsing bug.

Common Pitfalls

The most common mistake is using split("\n") on Windows-style input and forgetting that each element may still end with \r.

Another issue is calling strip() too aggressively and removing meaningful leading spaces from indented or formatted text.

People also often combine splitting and filtering in one expression before they have decided whether blank lines should be preserved.

Finally, loading very large files into one string is usually unnecessary if simple line-by-line iteration would do the job.

Summary

  • Use splitlines() when you want logical lines across different newline conventions.
  • Use split("\n") when exact delimiter behavior and trailing empties matter.
  • Treat blank-line filtering as a separate decision from line splitting.
  • Iterate over files directly when the source is large.
  • Decode bytes to text before splitting into lines.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.