781

Is this the cleanest way to write a list to a file, since writelines() doesn't insert newline characters?

file.writelines(["%s\n" % item  for item in list])

It seems like there would be a standard way...

APerson
  • 7,304
  • 5
  • 32
  • 48
Josh Arenberg
  • 8,318
  • 4
  • 18
  • 15

22 Answers22

1079

You can use a loop:

with open('your_file.txt', 'w') as f:
    for item in my_list:
        f.write("%s\n" % item)

In Python 2, you can also use

with open('your_file.txt', 'w') as f:
    for item in my_list:
        print >> f, item

If you're keen on a single function call, at least remove the square brackets [], so that the strings to be printed get made one at a time (a genexp rather than a listcomp) -- no reason to take up all the memory required to materialize the whole list of strings.

Alex Martelli
  • 762,786
  • 156
  • 1,160
  • 1,345
  • 8
    This isn't terribly complex, but why not just use pickle or json so that you don't have to worry about the serialization and deserialization? – Jason Baker May 22 '09 at 18:37
  • 101
    For example because you want an output text file that can be easily read, edited, etc, with one item per line. Hardly a rare desire;-). – Alex Martelli May 23 '09 at 14:40
  • 1
    I found that the \n in the first one was redundant on Python 2.7/Windows – Jorge Rodriguez Aug 13 '14 at 03:19
  • 17
    This will write an extra newline character at the end... rather than loop, you could just write `thefile.write('\n'.join(thelist))` – Tgsmith61591 Aug 23 '16 at 17:14
  • 4
    I would add: "Be careful with the list datatype". I was getting some weird results, maybe this can help someone: `thefile.write(str(item) + "\n")` – iipr May 11 '17 at 14:56
  • 1
    Just a little simpler for python 3.7'ish `f.write(f'{item}\n')` – Thom Ives Oct 05 '19 at 20:30
435

What are you going to do with the file? Does this file exist for humans, or other programs with clear interoperability requirements?

If you are just trying to serialize a list to disk for later use by the same python app, you should be pickleing the list.

import pickle

with open('outfile', 'wb') as fp:
    pickle.dump(itemlist, fp)

To read it back:

with open ('outfile', 'rb') as fp:
    itemlist = pickle.load(fp)
SingleNegationElimination
  • 137,315
  • 28
  • 247
  • 284
348

The simpler way is:

with open("outfile", "w") as outfile:
    outfile.write("\n".join(itemlist))

You could ensure that all items in item list are strings using a generator expression:

with open("outfile", "w") as outfile:
    outfile.write("\n".join(str(item) for item in itemlist))

Remember that all itemlist list need to be in memory, so, take care about the memory consumption.

osantana
  • 5,452
  • 2
  • 17
  • 25
  • 25
    No trailing newline, uses 2x space compared to the loop. – Dave May 22 '09 at 18:13
  • 8
    Of course the first question that springs to mind is whether or not the OP needs it to end in a newline and whether or not the amount of space matters. You know what they say about premature optimizations. – Jason Baker May 22 '09 at 18:40
  • 18
    A downside: This constructs the entire contents for the file in memory before writing any of them out, so peak memory usage may be high. – RobM Feb 17 '11 at 17:13
  • 1
    Note from [the documentation of the os module](http://docs.python.org/library/os.html): _Do not use os.linesep as a line terminator when writing files opened in text mode (the default); use a single '\n' instead, on all platforms._ – jilles de wit Apr 26 '11 at 13:03
  • 4
    I can never get this to work. I get this error: "text = '\n'.join(namelist) + '\n' TypeError: sequence item 0: expected string, list found" – Dan Aug 09 '11 at 03:16
  • 2
    You've to ensure that all elements in 'namelist' are strings. – osantana Aug 10 '11 at 18:19
  • 1
    If you want to add a trailing newline here, simply add a `+ "\n"` at the end. Don't see what problem @Dave has with this. – mozzbozz Nov 05 '14 at 13:39
  • For long list, this method is much much faster. – xlash Mar 07 '18 at 15:17
  • 1
    the clean solution for people who don't care about any memory limitations. – Geoff Paul Bremner Nov 28 '19 at 16:03
  • Executable code in relation to the comments [first](https://stackoverflow.com/questions/899103/writing-a-list-to-a-file-with-python#comment706680_899149) from @Dave , and [second](https://stackoverflow.com/questions/899103/writing-a-list-to-a-file-with-python#comment42098718_899149) (from @mozzbozz) `>>> with open("outfile", "w") as outfile:` \n `... outfile.write("\n".join(itemlist))` \n `... outfile.write("\n")` \n `...` \n `>>>` (Written as if from the interactive Python prompt to make indentation clear. Written for my case, where lists will (mathematically) never be longer than 50. – bballdave025 Oct 12 '20 at 22:58
101

Using Python 3 and Python 2.6+ syntax:

with open(filepath, 'w') as file_handler:
    for item in the_list:
        file_handler.write("{}\n".format(item))

This is platform-independent. It also terminates the final line with a newline character, which is a UNIX best practice.

Starting with Python 3.6, "{}\n".format(item) can be replaced with an f-string: f"{item}\n".

orluke
  • 1,944
  • 1
  • 16
  • 15
  • 1
    i dont want to add "\n" for the last item, what to do? dont want if condition – pyd Feb 16 '18 at 06:50
  • 5
    @pyd Replace the for loop with `file_handler.write("\n".join(str(item) for item in the_list))` – orluke Feb 21 '18 at 19:47
93

Yet another way. Serialize to json using simplejson (included as json in python 2.6):

>>> import simplejson
>>> f = open('output.txt', 'w')
>>> simplejson.dump([1,2,3,4], f)
>>> f.close()

If you examine output.txt:

[1, 2, 3, 4]

This is useful because the syntax is pythonic, it's human readable, and it can be read by other programs in other languages.

Jason Baker
  • 171,942
  • 122
  • 354
  • 501
39

I thought it would be interesting to explore the benefits of using a genexp, so here's my take.

The example in the question uses square brackets to create a temporary list, and so is equivalent to:

file.writelines( list( "%s\n" % item for item in list ) )

Which needlessly constructs a temporary list of all the lines that will be written out, this may consume significant amounts of memory depending on the size of your list and how verbose the output of str(item) is.

Drop the square brackets (equivalent to removing the wrapping list() call above) will instead pass a temporary generator to file.writelines():

file.writelines( "%s\n" % item for item in list )

This generator will create newline-terminated representation of your item objects on-demand (i.e. as they are written out). This is nice for a couple of reasons:

  • Memory overheads are small, even for very large lists
  • If str(item) is slow there's visible progress in the file as each item is processed

This avoids memory issues, such as:

In [1]: import os

In [2]: f = file(os.devnull, "w")

In [3]: %timeit f.writelines( "%s\n" % item for item in xrange(2**20) )
1 loops, best of 3: 385 ms per loop

In [4]: %timeit f.writelines( ["%s\n" % item for item in xrange(2**20)] )
ERROR: Internal Python error in the inspect module.
Below is the traceback from this internal error.

Traceback (most recent call last):
...
MemoryError

(I triggered this error by limiting Python's max. virtual memory to ~100MB with ulimit -v 102400).

Putting memory usage to one side, this method isn't actually any faster than the original:

In [4]: %timeit f.writelines( "%s\n" % item for item in xrange(2**20) )
1 loops, best of 3: 370 ms per loop

In [5]: %timeit f.writelines( ["%s\n" % item for item in xrange(2**20)] )
1 loops, best of 3: 360 ms per loop

(Python 2.6.2 on Linux)

RobM
  • 7,365
  • 2
  • 40
  • 37
24

Because i'm lazy....

import json
a = [1,2,3]
with open('test.txt', 'w') as f:
    f.write(json.dumps(a))

#Now read the file back into a Python list object
with open('test.txt', 'r') as f:
    a = json.loads(f.read())
Big Sam
  • 781
  • 6
  • 7
  • are lists json serializable? – kRazzy R Jan 04 '18 at 22:25
  • 1
    Yes indeed, they are! – Big Sam Jan 04 '18 at 22:33
  • 1
    import json ; test_list = [1,2,3]; list_as_a_string = json.dumps(test_list); #list_as_a_string is now the string '[1,2,3]' – Big Sam Jan 04 '18 at 22:42
  • I'm doing this `with open ('Sp1.txt', 'a') as outfile:` `json.dump (sp1_segments, outfile)` `logger.info ("Saved sp_1 segments")` ; problem is my program runs thrice, and the results from three runs are getting mashed up. is there any way to add 1-2 empty lines so that the results from each run are discernible? – kRazzy R Jan 04 '18 at 23:49
  • 1
    Absolutely! could you instead do ```json.dump(sp1_segments + "\n\n", outfile)```? – Big Sam Jan 05 '18 at 18:06
20

Serialize list into text file with comma sepparated value

mylist = dir()
with open('filename.txt','w') as f:
    f.write( ','.join( mylist ) )
themadmax
  • 2,037
  • 1
  • 24
  • 31
16

In General

Following is the syntax for writelines() method

fileObject.writelines( sequence )

Example

#!/usr/bin/python

# Open a file
fo = open("foo.txt", "rw+")
seq = ["This is 6th line\n", "This is 7th line"]

# Write sequence of lines at the end of the file.
line = fo.writelines( seq )

# Close opend file
fo.close()

Reference

http://www.tutorialspoint.com/python/file_writelines.htm

Marvin W
  • 2,985
  • 22
  • 15
13
file.write('\n'.join(list))
mtasic85
  • 3,496
  • 2
  • 17
  • 27
8
with open ("test.txt","w")as fp:
   for line in list12:
       fp.write(line+"\n")
shankar
  • 287
  • 3
  • 12
7

You can also use the print function if you're on python3 as follows.

f = open("myfile.txt","wb")
print(mylist, file=f)
Nandita Damaraju
  • 153
  • 2
  • 11
  • isn't it only put one line in myfile.txt, something like: ['a','b','c'] instead of writing each a,b,c on each line. – Harry Duong Mar 24 '17 at 05:00
7

In python>3 you can use print and * for argument unpacking:

with open("fout.txt", "w") as fout:
    print(*my_list, sep="\n", file=fout)
bricoletc
  • 123
  • 1
  • 5
4

Why don't you try

file.write(str(list))
Bob
  • 119
  • 4
3

Using numpy.savetxt is also an option:

import numpy as np

np.savetxt('list.txt', list, delimiter="\n", fmt="%s")
kamilazdybal
  • 173
  • 7
2

This logic will first convert the items in list to string(str). Sometimes the list contains a tuple like

alist = [(i12,tiger), 
(113,lion)]

This logic will write to file each tuple in a new line. We can later use eval while loading each tuple when reading the file:

outfile = open('outfile.txt', 'w') # open a file in write mode
for item in list_to_persistence:    # iterate over the list items
   outfile.write(str(item) + '\n') # write to the file
outfile.close()   # close the file 
petezurich
  • 6,779
  • 8
  • 29
  • 46
2

You can also go through following:

Example:

my_list=[1,2,3,4,5,"abc","def"]
with open('your_file.txt', 'w') as file:
    for item in my_list:
        file.write("%s\n" % item)

Output:

In your_file.txt items are saved like:

1

2

3

4

5

abc

def

Your script also saves as above.

Otherwise, you can use pickle

import pickle
my_list=[1,2,3,4,5,"abc","def"]
#to write
with open('your_file.txt', 'wb') as file:
    pickle.dump(my_list, file)
#to read
with open ('your_file.txt', 'rb') as file:
    Outlist = pickle.load(file)
print(Outlist)

Output: [1, 2, 3, 4, 5, 'abc', 'def']

It save dump the list same as a list when we load it we able to read.

Also by simplejson possible same as above output

import simplejson as sj
my_list=[1,2,3,4,5,"abc","def"]
#To write
with open('your_file.txt', 'w') as file:
    sj.dump(my_list, file)

#To save
with open('your_file.txt', 'r') as file:
    mlist=sj.load(file)
print(mlist)
MRUNAL MUNOT
  • 167
  • 1
  • 12
1

Another way of iterating and adding newline:

for item in items:
    filewriter.write(f"{item}" + "\n")
Alex
  • 84
  • 7
0

Redirecting stdout to a file might also be useful for this purpose:

from contextlib import redirect_stdout
with open('test.txt', 'w') as f:
  with redirect_stdout(f):
     for i in range(mylst.size):
        print(mylst[i])
Youjun Hu
  • 458
  • 2
  • 12
-1

In Python3 You Can use this loop

with open('your_file.txt', 'w') as f:
    for item in list:
        f.print("", item)
Nikhil B
  • 91
  • 6
-2

Let avg be the list, then:

In [29]: a = n.array((avg))
In [31]: a.tofile('avgpoints.dat',sep='\n',dtype = '%f')

You can use %e or %s depending on your requirement.

cosmin
  • 20,422
  • 5
  • 39
  • 57
-4
poem = '''\
Programming is fun
When the work is done
if you wanna make your work also fun:
use Python!
'''
f = open('poem.txt', 'w') # open for 'w'riting
f.write(poem) # write text to file
f.close() # close the file

How It Works: First, open a file by using the built-in open function and specifying the name of the file and the mode in which we want to open the file. The mode can be a read mode (’r’), write mode (’w’) or append mode (’a’). We can also specify whether we are reading, writing, or appending in text mode (’t’) or binary mode (’b’). There are actually many more modes available and help(open) will give you more details about them. By default, open() considers the file to be a ’t’ext file and opens it in ’r’ead mode. In our example, we first open the file in write text mode and use the write method of the file object to write to the file and then we finally close the file.

The above example is from the book "A Byte of Python" by Swaroop C H. swaroopch.com

vayah
  • 9
  • 1