211

Now I use:

pageHeadSectionFile = open('pagehead.section.htm','r') output = pageHeadSectionFile.read() pageHeadSectionFile.close() 

But to make the code look better, I can do:

output = open('pagehead.section.htm','r').read() 

When using the above syntax, how do I close the file to free up system resources?

6
  • 23
    There is nothing inherently more attractive about one-liners. Code is read far more often than it is written, and should be written for comprehension, not for "coolness." The only exception is when there is a well-known idiom in a language, but I am unaware of one in this case. Commented Nov 4, 2011 at 15:36
  • 25
    @drdwilcox: Cryptic one-liners are bad, declarative one-liners are good. There is no reason (at least I cannot see one), why there is no function wrapper in the core to read a file (such common need) in a single function call. Something like contents = os.readfile(path). If I wanted to do something fancier, then ok, I'd happily use with open(path) as fd: contents = fd.read(). Of course one can write its own wrapper, but that's what the core is for, to provide the useful to abstractions to programmers. Commented Jul 26, 2013 at 19:36
  • 15
    It's true that code is read far more than it's written, but the implication that longer code is just as good as short code couldn't be more wrong. If you invest time in making your code as short as possible (without resorting to clever tricks that are hard to understand), that investment will pay off over and over when the code is read. Every line you write is a disservice to anyone reading your code, so you should strive to write as little as possible. Remember the famous quote from Pascal: "I made this letter longer only because I have not had the leisure to make it shorter." Commented Feb 13, 2019 at 20:00
  • 2
    One may be in an environment where they need to write one-liners, like when debugging in pdb. Don't belittle other people's questions. Commented Nov 3, 2020 at 15:33
  • 2
    Vertical space is valuable. If I can read a whole funcion in one screen I am happy. Lots of empty space doesn't make your code more readable, it is just a habbit. Commented Aug 17, 2021 at 18:20

11 Answers 11

255

You don't really have to close it - Python will do it automatically either during garbage collection or at program exit. But as @delnan noted, it's better practice to explicitly close it for various reasons.

So, what you can do to keep it short, simple and explicit:

with open('pagehead.section.htm', 'r') as f: output = f.read() 

Now it's just two lines and pretty readable, I think.

Sign up to request clarification or add additional context in comments.

15 Comments

@1qazxsw2 If you use the with statement the file resource will be closed properly for you.
Re first sentence: Python will close it eventually. But that doesn't mean you should forget about closing. Even with refcounting, the file may stay open far longer than you think and want (e.g. if it happens to be referred to by cycles). This goes thrice in Python implementations that have a decent GC, where you have no guarantee that anything is GC'd at any particular time. Even the CPython documentation says you shouldn't rely on GC for cleanup like this. The latter part of the answer should be bold.
If you really need a one-liner, it is possible to put the output = f.read() part on the same line after the :.
"open read and close a file in 1 line of code" this is two lines, and does not answer the question.
Answer is obsolete. Correct answer using modern python is Path('pagehead.section.htm').read_text()
|
207

Python Standard Library Pathlib module does what you looking for:

Path('pagehead.section.htm').read_text() 

Don't forget to import Path:

jsk@dev1:~$ python3 Python 3.5.2 (default, Sep 10 2016, 08:21:44) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from pathlib import Path >>> (Path("/etc") / "hostname").read_text() 'dev1.example\n' 

On Python 27 install backported pathlib or pathlib2

2 Comments

The other answers proposing with are fine, but with is a statement, not an expression. This pathlib answer is the only reply to the original question that can be embedded in a Python expression. Something like SECRET_KEY = os.environ.get('SECRET_KEY') or pathlib.Path('SECRET_KEY').read_bytes()
Nice addition of pathlib! « The file is opened then closed. »
27

Using CPython, your file will be closed immediately after the line is executed, because the file object is immediately garbage collected. There are two drawbacks, though:

  1. In Python implementations different from CPython, the file often isn't immediately closed, but rather at a later time, beyond your control.

  2. In Python 3.2 or above, this will throw a ResourceWarning, if enabled.

Better to invest one additional line:

with open('pagehead.section.htm','r') as f: output = f.read() 

This will ensure that the file is correctly closed under all circumstances.

Comments

26

No need to import any special libraries to do this.

Use normal syntax and it will open the file for reading then close it.

with open("/etc/hostname","r") as f: print f.read() 

or

with open("/etc/hosts","r") as f: x = f.read().splitlines() 

which gives you an array x containing the lines, and can be printed like so:

for line in x: print line 

These one-liners are very helpful for maintenance - basically self-documenting.

Comments

14

What you can do is to use the with statement, and write the two steps on one line:

>>> with open('pagehead.section.htm', 'r') as fin: output = fin.read(); >>> print(output) some content 

The with statement will take care to call __exit__ function of the given object even if something bad happened in your code; it's close to the try... finally syntax. For object returned by open, __exit__ corresponds to file closure.

This statement has been introduced with Python 2.6.

1 Comment

Small clarification: according to the documentation with was introduced in Python 2.5, but had to be explicitly imported from __future__. It became available from all contexts in Python 2.6.
6

I think the most natural way for achieving this is to define a function.

def read(filename): f = open(filename, 'r') output = f.read() f.close() return output 

Then you can do the following:

output = read('pagehead.section.htm') 

1 Comment

This code doesn't make sense. Just return open(filename, 'r').read() does the same thing, because your f.close is not guaranteed to be called and the close will be called by garbage collection anyway when the function exits.
5

use ilio: (inline io):

just one function call instead of file open(), read(), close().

from ilio import read content = read('filename') 

Comments

1
with open('pagehead.section.htm')as f:contents=f.read() 

5 Comments

How is this any different from the top 3 answers?
The biggest difference is that it is only one line as the question specified. Personally I can't find any beyond that but feel free to critique my work rather than actually contributing to the question yourself.
The shortest, built-in way to achieve opening, reading, and closing a file in Python is using 2 logical lines whether it's condensed down to 1 line or not. So I don't see this answer to be effectively any different from the 3 original answers.
It does not matter if its 'effectively' different. I got to this page looking for one-line syntax that might be used with python -c on the command line, so posting 2-line answers does not help.
@user5359531 I don't see your point: do you know that you can quote python expressions with ", use ; to append two instructions, and delete newline after : ? Following expression works just fine for me : $> python -c "with open('some file', 'r') as f: print(next(f))"
1

I frequently do something like this when I need to get a few lines surrounding something I've grepped in a log file:

$ grep -n "xlrd" requirements.txt | awk -F ":" '{print $1}' 54 $ python -c "with open('requirements.txt') as file: print ''.join(file.readlines()[52:55])" wsgiref==0.1.2 xlrd==0.9.2 xlwt==0.7.5 

1 Comment

Completely unrelated to the original topic, but you should look into grep -A <n>, grep -B <n>, and grep -C <n>, if it is helpful. More info: stackoverflow.com/a/9083/1830159
0

Using more_itertools.with_iter, it is possible to open, read, close and assign an equivalent output in one line (excluding the import statement):

import more_itertools as mit output = "".join(line for line in mit.with_iter(open("pagehead.section.htm", "r"))) 

Although possible, I would look for another approach other than assigning the contents of a file to a variable, i.e. lazy iteration - this can be done using a traditional with block or in the example above by removing join() and iterating output.

2 Comments

You can import inside the oneliner as well. "".join(line for line in __import__('more_itertools').with_iter(open("pagehead.section.htm", "r"))) This works just fine, and eliminates the need for a line for the import.
I completely agree with you. However while discussing solving tasks with oneliners, I've often found myself in arguments where the agreed outcome should be a single line of code pasted into a fresh python shell. Such challenges rarely conform to pep8. It's in no way a good practice for writing code, it was only meant as a tip to remove the need for imports.
0

If you want that warm and fuzzy feeling just go with with.

For python 3.6 I ran these two programs under a fresh start of IDLE, giving runtimes of:

0.002000093460083008 Test A 0.0020003318786621094 Test B: with guaranteed close 

So not much of a difference.

#--------*---------*---------*---------*---------*---------*---------*---------* # Desc: Test A for reading a text file line-by-line into a list #--------*---------*---------*---------*---------*---------*---------*---------* import sys import time # # MAINLINE if __name__ == '__main__': print("OK, starting program...") inTextFile = '/Users/Mike/Desktop/garbage.txt' # # Test: A: no 'with; c=[] start_time = time.time() c = open(inTextFile).read().splitlines() print("--- %s seconds ---" % (time.time() - start_time)) print("OK, program execution has ended.") sys.exit() # END MAINLINE 

OUTPUT:

OK, starting program... --- 0.002000093460083008 seconds --- OK, program execution has ended. #--------*---------*---------*---------*---------*---------*---------*---------* # Desc: Test B for reading a text file line-by-line into a list #--------*---------*---------*---------*---------*---------*---------*---------* import sys import time # # MAINLINE if __name__ == '__main__': print("OK, starting program...") inTextFile = '/Users/Mike/Desktop/garbage.txt' # # Test: B: using 'with' c=[] start_time = time.time() with open(inTextFile) as D: c = D.read().splitlines() print("--- %s seconds ---" % (time.time() - start_time)) print("OK, program execution has ended.") sys.exit() # END MAINLINE 

OUTPUT:

OK, starting program... --- 0.0020003318786621094 seconds --- OK, program execution has ended. 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.