I would like to insert the following function into a Python script, concerning a file, and I haven't found how to write it yet:
if the file is opened, close it
if it is already closed, do nothing
Any help will be really much appreciated. Thank you in advance!
You write this as f.close().
In Python 3.x, IOBase.close says:
Flush and close this stream. This method has no effect if the file is already closed.
Likewise, in Python 2.x, file.close says:
Close the file … Calling close() more than once is allowed.
Of course if you read the docs, you'll notice that files (whether 3.x IOBase or 2.x file) also have a closed attribute, so if you really wanted to write what you were asking for explicitly, you could:
if not f.closed:
f.close()
But that has no benefit over just calling f.close(). Unless you want to make sure that some file-like objects that aren't 100% file-like raise an inscrutable AttributeError instead of just working as you'd like, but I doubt you want that.
f.close() is the way to close a file. Python details how to use file operations Here in python 2 and here in Python3
Related
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 a.b, 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 i.e 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 following code is written in the morph.py file:
with open("morph.py", "r+") as f:
old = f.read() # read everything in the file
f.seek(0,2) # rewind
f.write("1") # write the new line before
a="BAD"
a1="Worked"
print a
The idea is that the morph.py file will be rewritten, and the text "Worked" will be printed.
This is not the case, I think it has to do with how Python interpreter loads the files. The only thing that makes sense is that the whole file is loaded, and then run.
Can somebody shed some light? Is it even possible to have self morphing code in python?
Partially related question:
Self decompressing and executing code in python
Not in the way you're trying to do it.
Before Python starts executing any piece of code, it compiles it into a bytecode representation, which is much faster to execute than reading line-by-line. This means that after Python has compiled the file, no changes to the file will be reflected in currently-running code.
However, you can manually load code from strings by using compile, exec, or eval. You can use this to create a program that is passed its own source code, alters and returns it, and executes the modified source code.
When I run the file the first time it outputs:
BAD
When I run it a second time it outputs:
Worked
Any subsequent times it will give an error:
... name 'a11' is not defined
When you run python on a file, it will load the file, then convert it to bytecode, then execute the bytecode. The file has already undergone conversion when you change the file, so you see no effect.
This question already has an answer here:
In the Inline "open and write file" is the close() implicit?
(1 answer)
Closed 9 years ago.
I've seen this idiom in Dive Into Python 3:
l = list(open('strcpy.c'))
The question is, how can I close the file?
Is something happening behind the scenes?
I couldn't find this information in the book.
The file will be closed when its object is garbage-collected. In CPython, this happens pretty much immediately after that line is executed, because the file is never assigned to a variable. In other Pythons, such as Jython or IronPython, this may not happen right away (or at all), though all open files are always closed when the process exits.
For this reason, a better approach is to close the file explicitly using 'with':
with open("strcpy.c") as infile:
l = list(infile)
An advantage of this is that the file will be properly closed even if an exception occurs in reading it; you don't have to manually write code for this case using a try/except block.
A with statement can be written on one line if you want to stick with the concise one-liner. :-)
That said, I do sometimes use this idiom myself in short-running scripts where having the file open a wee bit longer than it strictly needs to be isn't a big deal. An advantage is that you don't clutter things up with a variable (infile in this case) pointing to a closed file.
From doc:
It is good practice to use the with keyword when dealing with file
objects. This has the advantage that the file is properly closed after
its suite finishes, even if an exception is raised on the way.
You can use it like this:
with open('strcpy.c') as f:
l = list(f)
Personally, I would never open a file without a context manager:
with open('strcpy.c') as myfile:
l = list(myfile)
# do stuff with l here
When using the context manager, the file is automagically closed at the end of the indentation block.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
check what files are open in Python
Hello,
Is it possible to obtain a list of all currently open file handles, I presume that they are stored somewhere in the environment.
I am interested in theis function as I would like to safely handle any files that are open when a fatal error is raised, i.e. close file handles and replace potentially corrupted files with the original files.
I have the handling working but without knowing what file handles are open, I am unable to implement this idea.
As an aside, when a file handle is initialised, can this be inherited by another imported method?
Thank you
lsof, /proc/pid/fd/
The nice way of doing this would be to modify your code to keep track of when it opens a file:
def log_open( *args, **kwargs ):
print( "Opening a file..." )
print( *args, **kwargs )
return open( *args, **kwargs )
Then, use log_open instead of open to open files. You could even do something more hacky, like modifying the File class to log itself. That's covered in the linked question above.
There's probably a disgusting, filthy hack involving the garbage collector or looking in __dict__ or something, but you don't want to do that unless you absolutely really truly seriously must.
If you're using python 2.5+ you can use the with keyword (though 2.5 needs `from future import with_statement)
with open('filename.txt', 'r') as f:
#do stuff here
pass
#here f has been closed and disposed properly - even with raised exceptions
I don't know what kind of catastrophic failure needs to bork the with statement, but I assume it's a really bad one. On WinXP, my quick unscientific test:
import time
with open('test.txt', 'w') as f:
f.write('testing\n')
while True:
time.sleep(1)
and then killing the process with Windows Task Manager still wrote the data to file.
I am on windows with Python 2.5. I have an open file for writing. I write some data. Call file close. When I try to delete the file from the folder using Windows Explorer, it errors, saying that a process still holds a handle to the file.
If I shutdown python, and try again, it succeeds.
It does close them.
Are you sure f.close() is getting called?
I just tested the same scenario and windows deletes the file for me.
Are you handling any exceptions around the file object? If so, make sure the error handling looks something like this:
f = open("hello.txt")
try:
for line in f:
print line
finally:
f.close()
In considering why you should do this, consider the following lines of code:
f = open('hello.txt')
try:
perform_an_operation_that_causes_f_to_raise_an_exception()
f.close()
except IOError:
pass
As you can see, f.close will never be called in the above code. The problem is that the above code will also cause f to not get garbage collected. The reason is that f will still be referenced in sys.traceback, in which case the only solution is to manually call close on f in a finally block or set sys.traceback to None (and I strongly recommend the former).
Explained in the tutorial:
with open('/tmp/workfile', 'r') as f:
read_data = f.read()
It works when you writing or pickling/unpickling, too
It's not really necessary that try finally block: Java way of doing things, not Python
I was looking for this, because the same thing happened to me. The question didn't help me, but I think I figured out what happened.
In the original version of the script I wrote, I neglected to add in a 'finally' clause to the file in case of an exception.
I was testing the script from the interactive prompt and got an exception while the file was open. What I didn't realize was that the file object wasn't immediately garbage-collected. After that, when I ran the script (still from the same interactive session), even though the new file objects were being closed, the first one still hadn't been, and so the file handle was still in use, from the perspective of the operating system.
Once I closed the interactive prompt, the problem went away, at which I remembered that exception occurring while the file was open and realized what had been going on. (Moral: Don't try to program on insufficient sleep. : ) )
Naturally, I have no idea if this is what happened in the case of the original poster, and even if the original poster is still around, they may not remember the specific circumstances, but the symptoms are similar, so I thought I'd add this as something to check for, for anyone caught in the same situation and looking for an answer.
I did it using intermediate file:
import os
f = open("report.tmp","w")
f.write("{}".format("Hello"))
f.close()
os.system("move report.tmp report.html") #this line is for Windows users