file.writelines() writes every item from an iterable of strings to an open file, in order, with nothing added between items. It does not insert newline characters for you—the same rule applies to write(). That surprise—lines glued together without \n—is the main reason people look up this method.
This page covers what writelines() does, how to add newlines, how it compares to write(), append mode, and common mistakes. For opening files, modes, and general writing patterns, see Python write to file. Examples use tempfile.TemporaryDirectory() so your project tree is untouched. Snippets use {run=false}—run them locally with python3.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
What does writelines() do in Python?
Call writelines() on a file object opened for writing (w or a). Pass any iterable that yields strings—a list, tuple, or generator:
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "out.txt"
lines = ["This", "is", "GoLinuxCloud"]
with open(path, "w") as f:
f.writelines(lines)
print(repr(path.read_text()))You should see 'ThisisGoLinuxCloud'—three strings written back-to-back with no separator.
Signature from the file object docs:
file.writelines(lines)lines: iterable of strings (text mode) or bytes (binary mode)- Return value:
None(unlikewrite(), which returns the number of characters written)
writelines() is a convenience for “write many strings without building one big concatenated string first.” It still performs one write operation per iterable item internally; it is not a special fast path on all platforms, but it keeps your code clear when you already have a list of lines.
Python writelines() with newline
Neither writelines() nor write() adds \n for you. Put the newline inside each string:
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "out.txt"
lines = ["This\n", "is\n", "GoLinuxCloud\n"]
with open(path, "w") as f:
f.writelines(lines)
print(path.read_text())You should see three lines of text.
A compact pattern when you have bare lines without \n:
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "out.txt"
lines = ["This", "is", "GoLinuxCloud"]
with open(path, "w") as f:
f.writelines(line + "\n" for line in lines)
print(path.read_text())Same three-line output. A generator works fine—writelines() only needs an iterable, not a materialized list.
If you already use "\n".join(...), call write() on the joined string instead of writelines() on it. A string is iterable character-by-character, so writelines(joined) technically writes the same bytes but misuses the API and is harder to read:
# Prefer this:
f.write("\n".join(lines) + "\n")
# Not this (iterates characters of one string):
f.writelines("\n".join(lines))writelines() vs write()
write(s) |
writelines(lines) |
|
|---|---|---|
| Argument | One str (or bytes) |
Iterable of str (or bytes) |
| Newlines | You supply \n in s |
You supply \n in each item |
| Return value | Character (or byte) count | None |
| List of lines | TypeError if you pass a list |
Intended use case |
write() with one multiline string:
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "out.txt"
with open(path, "w") as f:
f.write("line1\nline2\n")
print(path.read_text())writelines() with a list:
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "out.txt"
with open(path, "w") as f:
f.writelines(["line1\n", "line2\n"])
print(path.read_text())Both produce the same file content. Use writelines() when you already hold a sequence of lines; use write() for a single blob or an f-string. Passing a list to write() raises TypeError: write() argument must be str, not list.
Append lines using writelines()
Mode a keeps existing content and writes new items at the end—same as with write():
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "log.txt"
with open(path, "w") as f:
f.write("existing\n")
with open(path, "a") as f:
f.writelines(["new1\n", "new2\n"])
print(path.read_text())You should see existing, then new1, then new2, each on its own line. Opening with w by mistake truncates the file before writelines() runs. See Python write to file for w vs a vs x.
Common mistakes with writelines()
Expecting automatic newlines. Items are concatenated as-is. If output looks like abcdef instead of three lines, add \n to each string or use line + "\n" for line in lines.
Passing a list to write(). Use writelines(the_list) or write("\n".join(the_list)).
Believing old tutorials that claim writelines() adds newlines but write() does not. Neither method adds line breaks; only your strings do.
Using writelines('\n'.join(lines)). join returns one string; writelines then iterates characters. The file may look correct, but write('\n'.join(lines)) expresses intent clearly.
Forgetting to open for writing. writelines() on a file opened with r raises io.UnsupportedOperation: not writable.
Mixing bytes and str in text mode. Text mode expects str iterables; binary mode (wb, ab) expects bytes.
Summary
writelines() writes each string from an iterable to a file in order and returns None. It does not append \n after each item—you must include newline characters in the strings or build them with line + "\n". Use writelines() for a list or generator of lines; use write() for one string. For append behavior, open with "a" before calling writelines(). For tabular exports, prefer csv.writer in read and write CSV over hand-built comma-separated lines.

