198

I want to prompt a user for a number of random numbers to be generated and saved to a file. He gave us that part. The part we have to do is to open that file, convert the numbers into a list, then find the mean, standard deviation, etc. without using the easy built-in Python tools.

I've tried using open but it gives me invalid syntax (the file name I chose was "numbers" and it saved into "My Documents" automatically, so I tried open(numbers, 'r') and open(C:\name\MyDocuments\numbers, 'r') and neither one worked).

AGN Gazer
  • 8,025
  • 2
  • 27
  • 45
user474713
  • 1,997
  • 2
  • 12
  • 3
  • `open(numbers, 'r')` should probably give a `NameError` unless you defined `numbers` somewhere earlier. As easy as Python is where you can start hammering away at it, I'd at least try to refer back to some texts to provide you with more structured answers and examples. – Nick T Oct 13 '10 at 17:19
  • 1
    @leoluk — Rolled back your changes as it looks like that's the crux of the OP's problem. – Ben Blank Oct 13 '10 at 21:15
  • `lines = list(file)` – Niraj Trivedi May 17 '18 at 12:00

8 Answers8

340
with open('C:/path/numbers.txt') as f:
    lines = f.read().splitlines()

this will give you a list of values (strings) you had in your file, with newlines stripped.

also, watch your backslashes in windows path names, as those are also escape chars in strings. You can use forward slashes or double backslashes instead.

Corey Goldberg
  • 59,062
  • 28
  • 129
  • 143
130

Two ways to read file into list in python (note these are not either or) -

  1. use of with - supported from python 2.5 and above
  2. use of list comprehensions

1. use of with

This is the pythonic way of opening and reading files.

#Sample 1 - elucidating each step but not memory efficient
lines = []
with open("C:\name\MyDocuments\numbers") as file:
    for line in file: 
        line = line.strip() #or some other preprocessing
        lines.append(line) #storing everything in memory!

#Sample 2 - a more pythonic and idiomatic way but still not memory efficient
with open("C:\name\MyDocuments\numbers") as file:
    lines = [line.strip() for line in file]

#Sample 3 - a more pythonic way with efficient memory usage. Proper usage of with and file iterators. 
with open("C:\name\MyDocuments\numbers") as file:
    for line in file:
        line = line.strip() #preprocess line
        doSomethingWithThisLine(line) #take action on line instead of storing in a list. more memory efficient at the cost of execution speed.

the .strip() is used for each line of the file to remove \n newline character that each line might have. When the with ends, the file will be closed automatically for you. This is true even if an exception is raised inside of it.

2. use of list comprehension

This could be considered inefficient as the file descriptor might not be closed immediately. Could be a potential issue when this is called inside a function opening thousands of files.

data = [line.strip() for line in open("C:/name/MyDocuments/numbers", 'r')]

Note that file closing is implementation dependent. Normally unused variables are garbage collected by python interpreter. In cPython (the regular interpreter version from python.org), it will happen immediately, since its garbage collector works by reference counting. In another interpreter, like Jython or Iron Python, there may be a delay.

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
  • 14
    This does not close the opened file. – sha Mar 14 '16 at 09:49
  • 1
    I don't know that the for loop is the most pythonic way to do this. The solution I just implemented is a hybrid of the two. (@sha it is noted that it doesn't close the file.) – jdj081 May 31 '17 at 16:39
  • Approach 1 is not very pythonic. Instead of creating the empty list first and appending inside your own loop, you can just use a list comprehension. But you don't have to include everything (like file i/o) directly in your comprehension, as in Approach 2. Instead... combining a list comprehension inside a "with" statement seems like the most idiomatic way to go. i.e.: `with open('foo') as f: lines = [line.strip() for line in f]` – Corey Goldberg Jun 19 '17 at 03:54
  • @CoreyGoldberg I agree on your observation. I have written it explicitly so that I can explain the value of each statement. I have added an alternate more concise code now. thanks for sharing your feedback. – Srikar Appalaraju Jun 19 '17 at 04:13
  • @SrikarAppal your new Sample 3 doesn't create a list like the OP asked for – Corey Goldberg Jun 20 '17 at 00:24
  • 1
    @CoreyGoldberg I agree. I was showing that Sample 3 is more memory efficient than collecting all data in a list. Digressed a little bit from what is asked from but I mentioned it as Samples 1 and 2 are not memory efficient. – Srikar Appalaraju Jun 21 '17 at 09:11
  • @SrikarAppalaraju sample 3 is only memory efficient because it doesn't actually create the list, which was the entire point of the question. It specifically states: "How do you read a file into a list in Python?". While sample 3 might be more memory-efficient for processing, it's completely unrelated to the question being asked. – Corey Goldberg Jun 23 '17 at 16:50
  • 1
    @CoreyGoldberg please read my above comment. I am aware its not what the person has asked. But as experienced programmers its our duty to show efficient ways where applicable. I feel what I present in sample 3 is not unrelated! it's a memory efficient way to process data on the fly than storing the whole thing in a list and then processing it... hence I present this at the last after answering his actual question. – Srikar Appalaraju Jun 24 '17 at 04:43
70
f = open("file.txt")
lines = f.readlines()

Look over here. readlines() returns a list containing one line per element. Note that these lines contain the \n (newline-character) at the end of the line. You can strip off this newline-character by using the strip()-method. I.e. call lines[index].strip() in order to get the string without the newline character.

As joaquin noted, do not forget to f.close() the file.

Converting strint to integers is easy: int("12").

phimuemue
  • 34,669
  • 9
  • 84
  • 115
  • 1
    beware that `strip()` removes ALL white space from the start and end of a string - if you need white space you can use `lines[index][:-1]` instead (though make sure the last line has a newline character at the end!). – drevicko May 20 '14 at 12:35
  • `file = open('C:\Data\TempPlayer.txt','r') lines = list(file) for line in lines:` – Niraj Trivedi May 17 '18 at 11:59
16

The pythonic way to read a file and put every lines in a list:

from __future__ import with_statement #for python 2.5
with open('C:/path/numbers.txt', 'r') as f:
    lines = f.readlines()

Then, assuming that each lines contains a number,

numbers =[int(e.strip()) for e in lines]
ohe
  • 3,461
  • 3
  • 26
  • 50
  • 1
    +1 for the with statement usage; though his school would have to be really behind the times for him to have to use a `__future__` import. – Aphex Oct 13 '10 at 19:27
9

You need to pass a filename string to open. There's an extra complication when the string has \ in it, because that's a special string escape character to Python. You can fix this by doubling up each as \\ or by putting a r in front of the string as follows: r'C:\name\MyDocuments\numbers'.

Edit: The edits to the question make it completely different from the original, and since none of them was from the original poster I'm not sure they're warrented. However it does point out one obvious thing that might have been overlooked, and that's how to add "My Documents" to a filename.

In an English version of Windows XP, My Documents is actually C:\Documents and Settings\name\My Documents. This means the open call should look like:

open(r"C:\Documents and Settings\name\My Documents\numbers", 'r')

I presume you're using XP because you call it My Documents - it changed in Vista and Windows 7. I don't know if there's an easy way to look this up automatically in Python.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
8

To summarize a bit from what people have been saying:

f=open('data.txt', 'w') # will make a new file or erase a file of that name if it is present
f=open('data.txt', 'r') # will open a file as read-only
f=open('data.txt', 'a') # will open a file for appending (appended data goes to the end of the file)

If you wish have something in place similar to a try/catch

with open('data.txt') as f:
    for line in f:
        print line

I think @movieyoda code is probably what you should use however

Tom
  • 1,986
  • 2
  • 18
  • 29
  • this "summary" provides nothing new and gives information that doesn't relate to the question. (furthermore, the example has nothing to do with try/catch... I have no idea why that was mentioned at all) – Corey Goldberg Dec 12 '16 at 23:13
  • @CoreyGoldberg summaries generally don't provide new information, they simply summarize ;P. But FWIW the "new" info my answer has is around `w` and `a` options when using `open`. OP's issue is with opening a file that he/she wants to process with python. The context manager handles closing of the file, without a context manager you would need a way to ensure the file gets closed maybe a `finally: f.close()`. (related http://stackoverflow.com/a/8775008/465270) – Tom Dec 13 '16 at 16:51
7
hdl = open("C:/name/MyDocuments/numbers", 'r')
milist = hdl.readlines()
hdl.close()
joaquin
  • 82,968
  • 29
  • 138
  • 152
0

If you have multiple numbers per line and you have multiple lines, you can read them in like this:

    #!/usr/bin/env python

    from os.path import dirname

    with open(dirname(__file__) + '/data/path/filename.txt') as input_data:
        input_list= [map(int,num.split()) for num in input_data.readlines()]
Stefan Gruenwald
  • 2,582
  • 24
  • 30