简体   繁体   中英

Is it safe to open a file, write to it and NOT close it?

I have quite a large Python(3) script that I'm trying to optimize.
To my understanding when you use with open(..., ...) as x you DON'T need to use .close() at the end of the "with" block (it is automatically closed).

I also know that you SHOULD add .close() (if you are not using with ) after you are done manipulating the file, like this:

f = open(..., ...)
f.write()
f.close()

In an attempt to shove 3 lines (above) into 1 line I tried to change this:

with open(location, mode) as packageFile:
    packageFile.write()

Into this:

open(location, mode).write(content).close()

Unfortunately this did not work and I got this error:

Traceback (most recent call last):
  File "test.py", line 20, in <module>
    one.save("one.txt", sample)
  File "/home/nwp/Desktop/Python/test/src/one.py", line 303, in save
    open(location, mode).write(content).close()
AttributeError: 'int' object has no attribute 'close'

The same line works fine when I remove the .close() like this:

open(location, mode).write(content)

Why didn't open(location, mode).write(content).close() work and is it safe to omit the .close() function?

I also know that you SHOULD add .close() after you are done manipulating the file

Not if you're using with .

Why didn't open(location, mode).write(content).close() work

Because instead of trying to close the file, you're trying to close the return value of the write method call, which is an integer. You can't close an integer.

is it safe to omit the .close() function?

No. If you ever run this code on a different Python implementation, or if CPython ever abandons reference counting, your write could be arbitrarily delayed or even lost completely.

If you really want to shove this into a single line, you can write a single-line with statement:

with open(location, mode) as packageFile: packageFile.write(whatever)

This is discouraged, but much less discouraged than relying on the file object's finalizer to close the file for you.

That's because the . (dot) operator works from left to right. In ab , b is a message(method call) passed to a . Say

a.b.c...

reads

do b in a and return r1, then
do c in r1 and return r2, then
...

Now open returns an object that responds to read message, but read returns a str / bytes that has no method close .

Bdw, always use a context manager ie with with in such context. And I wonder what does this have to do with optimization, as you said you are doing this while optimizing a script.

It looks to me like the goal is for one function to occur right after another, however that isn't what is happening here.

open(location, mode) returns a file: https://docs.python.org/2/library/functions.html#open

In the syntax of

open(location, mode).write(content)

this is actually equivalent to

file = open(location, mode)
file.write(content)

the open statement becomes a type file which has a function called write(). The reason .close() doesn't work is that the file.write() doesn't have a function called close(). What this is trying to do is file.function().function().

In any case trying to optimize your code by reducing lines will not speed up performance noticeably, the normal with statement should be just as fast. Unless you are trying to go code golfing which is a whole other subject.

Have a good day!

is it safe to omit the .close() function?

In current versions of CPython the file will be closed at the end of the for loop because CPython uses reference counting as its primary garbage collection mechanism but that's an implementation detail, not a feature of the language.

Also directly quoting user2357112 : if you ever run this code on a different Python implementation, or if CPython ever abandons reference counting, your write could be arbitrarily delayed or even lost completely.

Why didn't open(location, mode).write(content).close() work?

This is because I was trying to call the .close() method on the return of open(location, mode).write(content) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM