2

I was wondering if there was any difference between doing:

var1 = open(filename, 'w').write("Hello world!")

and doing:

var1 = open(filename, 'w')
var1.write("Hello world!")
var1.close()

I find that there is no need (AttributeError) if I try to run close() after using the first method (all in one line).

I was wondering if one way was actually any different/'better' than the other, and secondly, what is Python actually doing here? I understand that open() returns a file object, but how come running all of the code in one line automatically closes the file too?

MackM
  • 2,906
  • 5
  • 31
  • 45
Deem
  • 7,007
  • 2
  • 19
  • 23

3 Answers3

7

Using with statement is preferred way:

with open(filename, 'w') as f:
    f.write("Hello world!")

It will ensure the file object is closed outside the with block.

falsetru
  • 357,413
  • 63
  • 732
  • 636
  • I absolutely agree with the information in the answer given here, but I do not believe it addresses the OP's question: "I was wondering if one way was actually any different/'better' than the other, and secondly, what is Python actually doing here?" in reference to the ways he has tried. – MackM Dec 09 '14 at 17:43
5

Let me example to you why your first instance wont work if you initial a close() method. This will be useful for your future venture into learning object orientated programming in Python

Example 1

When you run open(filename, 'w') , it will initialise and return an file handle object.

When you call for open(filename, 'w').write('helloworld'), you are calling the write method on the file object that you initiated. Since the write method do not return any value/object, var1 in your code above will be of NoneType

Example 2

Now in your second example, you are storing the file object as var1.

var1 will have the write method as well as the close method and hence it will work.

This is in contrast to what you have done in your first example.

falsetru have provided a good example of how you can read and write file using the with statement

Reading and Writing file using the with statement

to write

with open(filename, 'w') as f:
    f.write("helloworld") 

to read

with open(filename) as f:
    for line in f:
         ## do your stuff here

Using nested with statements to read/write multiple files at once

Hi here's an update to your question on the comments. Not too sure if this is the most pythonic way. But if you will like to use the with statement to read/write mulitple files at the same time using the with statement. What you can do is the nest the with statement within one another

For instance :

with open('a.txt', 'r') as a:
    with open('b.txt', 'w') as b:
        for line in a:
            b.write(line)

How and Why

The file object itself is a iterator. Therefore, you could iterator thru the file with a for loop. The file object contains the next() method, which, with each iteration will be called until the end of file is reached.

The with statement was introduced in python 2.5. Prior to python 2.5 to achieve the same effect, one have to

f = open("hello.txt")
try:
    for line in f:
        print line,
finally:
    f.close()

Now the with statement does that automatically for you. The try and finally statement are in place to ensure if there is any expection/error raised in the for loop, the file will be closed.

source : Python Built-in Documentation

Official documentations

Using the with statement, f.close() will be called automatically when it finishes. https://docs.python.org/2/tutorial/inputoutput.html

Happy venture into python

cheers, biobirdman

Community
  • 1
  • 1
biobirdman
  • 4,060
  • 1
  • 17
  • 15
  • Thank you very much, with regards to using the with statement to read, what if I wish to do the following: `data = open(filename).read()`? Is it possible to store the read() data from one file, and then write it to another file using the with statement both times? – Deem Dec 11 '14 at 05:49
  • @windmill I have added how to use with statementto open and read mulitple files at once – biobirdman Dec 11 '14 at 06:13
  • I see I see, one last question though, if you don't mind! You write for line in a: b.write(line). What does this 'line' refer to? The code works fine, but how does the term 'line' become linked to the string in the file? Sorry, I can't seem to find an explanation for this anywhere. – Deem Dec 11 '14 at 15:29
  • @Windmill let me know if my new edit answer explains the question you are looking for. basically the file object is like an list (an iterator to be correct) and you can loop thru it with a for loop. And yes, line here refer to a line in the file. The end of a logical line is represented by the token NEWLINE. – biobirdman Dec 12 '14 at 11:08
  • I (think) I get it, haha. Probably all a little complicated for me right now, I was just interested in how `line` somehow copied all the lines in the file. But thank you very much for your help, you've helped me understand the whole `write` situation a lot better. Thanks to the other answers too! – Deem Dec 16 '14 at 04:31
2

@falsetru's answer is correct, in terms of telling you how you're "supposed" to open files. But you also asked what the difference was between the two approaches you tried, and why they do what they do.

The answer to those parts of your question is that the first approach doesn't do what you probably think it does. The following code

var1 = open(filename, 'w').write("Hello world!")

is roughly equivalent to

tmp = open(filename, 'w')
var1 = tmp.write("Hello world!")
del tmp

Notice that the open() function returns a file object, and that file object has a write() method. But write() doesn't have any return value, so var1 winds up being None. From the official documentation for file.write(str):

Write a string to the file. There is no return value. Due to buffering, the string may not actually show up in the file until the flush() or close() method is called.

Now, the reason you don't need to close() is that the main implementation of Python (the one found at python.org, also called CPython) happens to garbage-collect objects that no longer have references to them, and in your one-line version, you don't have any reference to the file object once the statement completes. You'll find that your multiline version also doesn't strictly need the close(), since all references will be cleaned up when the interpreter exits. But see answers to this question for a more detailed explanation about close() and why it's still a good idea to use it, unless you're using with instead.

Community
  • 1
  • 1
John Y
  • 14,123
  • 2
  • 48
  • 72