Explicitly closing files in python [duplicate] - python

This question already has answers here:
Is explicitly closing files important?
(7 answers)
Closed 7 years ago.
Looking at Learning Python the Hard Way. Example 17 opens a file, copies it, and then closes it. One of the study drills is to simplify the program down as much as possible. However when I simplified it, there doesn't seem to be any file to close. What I'm trying to understand with the one liner is what, if anything, needs to be closed.
For example-
in_file = open(from_file)
indata = in_file.read()
...
in_file.close()
This can be simplified to
indata = open(from_file).read()
I understand it's good practice to close the file after opening it, but both indata and from_file are strings. From some more digging, I understand this is unpythonic and should be done in 2 lines for readability, which would result in a file descriptor. However there is no open file descriptor here to close. Did I miss something? Should I have a file descriptor to explicitly close?

Instead of doing this
indata = open(from_file).read()
You should have tried using the with keyword
with open(from_file) as f: indata = f.read()
In the former, you still have the file descriptor with you, even though you do not have any references left for it and there is no guarantee when the file will be closed. In the second approach, the file will be closed as soon as you are done with the statement execution.

The reason for this is that indata does not refer to a file object.
It refers to the data that the method read() returns, so when you try to call close() on that data, it will not work.
You need to keep separate references to open() and read() or look into using the with() builtin.

Related

Confusion about with statement python

I have a question regarding the use of with statements in python, as given below:
with open(fname) as f:
np.save(f,MyData)
If I'm not mistaken this opens the file fname in a secure manner, such that if an exception occurs the file is closed properly. then it writes MyData to the file. But what I would do is simply:
np.save(fname,MyData)
This would result in the same, MyData gets written to fname. I'm not sure I understand correctly why the former is better. I don't understand how this one-liner could keep the file "open" after it has ran the line. Therefore I also don't see how this could create issues when my code would crash afterwards.
Maybe this is a stupid/basic question, but I always thought that a cleaner code is a nicer code, so not having the extra with-loop seems just better to me.
numpy.save() handles the opening and closing in its code, however if you supply a file descriptor, it'll leave it open because it assumes you want to do something else with the file and if it closes the file it'll break the functionality for you.
Try this:
f = open(<file>)
f.close()
f.read() # boom
See also the hasattr(file, "write") ("file" as in descriptor or "handle" from file, buffer, or other IO) check, that checks if it's an object with a write() method and judging by that Numpy only assumes it's true.
However NumPy doesn't guarantee misusing its API e.g. if you create a custom structure that's a buffer and doesn't include write(), it'll be treated as a path and thus crash in the open() call.

Python 3. File state open or closed

Started to learn Python! Finally!
The line in question:
readMyFile=open("myFile.txt","r").read()
The line above reads the txt file into variable readMyFile. What I need to know:
How can i get the state of the myFile.txt file (if it's open or closed)? And how to close it if it's open? I know how to close it in case when I have:
readMyFile=open("myFile.txt","r")
readMyFile.close
But in the case above, variable contains text from the file, not the file object.
Thanks in advance!
When you write this:
readMyFile=open("myFile.txt","r").read()
… you can't get the state of the file, or close it, or anything else. You didn't store it, so you have no way to access it. There is no magic that lets you get back information that you threw away (otherwise, there'd be no point in throwing away information, and things like garbage collection couldn't possibly work).
The solution is to just not do that: any value that you want to use, store it in a variable (or a list or dict member, or an attribute of an instance, or whatever—just store it somewhere) and then (as you already know from your question) you can use it:
>>> myfile = open("myFile.txt","r")
>>> readMyFile = myFile.read()
>>> myFile.closed
False
>>> myFile.close()
>>> myFile.closed
True
Although in this case, there's an even better answer:
>>> with open("myFile.txt", "r") as myFile:
... readMyFile = myFile.read()
Now, myFile automatically gets closed at the end of the with statement, so you never have to worry about it.
Or, even better, you can wrap this in a function:
>>> def readfile(name):
... with open(name) as myFile:
... return myFile.read()
>>> readMyFile = readfile("myFile.txt")
… and none of your code even has to think about file objects, except the two lines of code inside readfile.
In a comment, you asked:
readMyFile=open("myFile.txt","r").read() is equal to 'with' solution in regard, that in both cases file will be closed and throwed away?
No, they're not equivalent.
The first version throws away your reference to the file object, so the file is now garbage—but you're leaving it up to Python to figure out that it's garbage and clean it up (which closes the file) for you whenever it notices and gets around to it.
The with version tells Python to clean up as soon as the with statement finishes.
As it happens, in this particular example, with CPython (the Python implementation you're probably using if you don't know which one you're using), Python will figure out that the value is garbage, and close the file, at the end of the statement, so there's no difference.
But that's not true in slightly different cases. And you can't actually know which cases it's true in without knowing a bit about the internals of how CPython works. And even then, if you run the same code in, say, PyPy instead of CPython, it will do something different. And that's why many Python programs used to mysteriously sometimes fail to write the last 300 bytes of a text file, or Python web servers would occasionally fail by running out of file handles, and so on—which is exactly the problem the with statement solves: you tell Python how long you need the value to live just by a simple indent, and it makes sure that value is cleaned up at the end.
try:
with open("myFile.txt","r") as fd:
readMyFile = fd.read()
Here you don't need to worry about closing the file. Sometimes too much files opened and not closing can cause some issues. Using a with statement Python will automatically close your file after with block.

Differences between file.read(), file.readline() and iterating over the file object [duplicate]

This question already has answers here:
Python readlines() usage and efficient practice for reading
(2 answers)
Closed 7 years ago.
I am new to computer science and am trying to create a function in python that will open files on my computer.
I know that the function f.readline() grabs the current line as a string, but what makes the functions f.read() and for line in f: different? Thanks.
read(x) will read up to x bytes in a file. If you don't supply the size, the entire file is read.
readline(x) will read up to x bytes or a newline, whichever comes first. If you don't supply a size, it will read all data until it hits a newline.
When using for line in f, it will call the next() method under the hood which really just does something very similar to readline (although I see references that is may do some buffering more efficiently since iterating usually means you are planning to read the entire file).
There is also readlines() which reads all lines into memory.

writing output for python not functioning

I am attempting to output a new txt file but it come up blank. I am doing this
my_file = open("something.txt","w")
#and then
my_file.write("hello")
Right after this line it just says 5 and then no text comes up in the file
What am I doing wrong?
You must close the file before the write is flushed. If I open an interpreter and then enter:
my_file = open('something.txt', 'w')
my_file.write('hello')
and then open the file in a text program, there is no text.
If I then issue:
my_file.close()
Voila! Text!
If you just want to flush once and keep writing, you can do that too:
my_file.flush()
my_file.write('\nhello again') # file still says 'hello'
my_file.flush() # now it says 'hello again' on the next line
By the way, if you happen to read the beautiful, wonderful documentation for file.write, which is only 2 lines long, you would have your answer (emphasis mine):
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.
If you don't want to care about closing file, use with:
with open("something.txt","w") as f:
f.write('hello')
Then python will take care of closing the file for you automatically.
As Two-Bit Alchemist pointed out, the file has to be closed. The python file writer uses a buffer (BufferedIOBase I think), meaning it collects a certain number of bytes before writing them to disk in bulk. This is done to save overhead when a lot of write operations are performed on a single file.
Also: When working with files, try using a with-environment to make sure your file is closed after you are done writing/reading:
with open("somefile.txt", "w") as myfile:
myfile.write("42")
# when you reach this point, i.e. leave the with-environment,
# the file is closed automatically.
The python file writer uses a buffer (BufferedIOBase I think), meaning
it collects a certain number of bytes before writing them to disk in
bulk. This is done to save overhead when a lot of write operations are
performed on a single file. Ref #m00am
Your code is also okk. Just add a statement for close file, then work correctly.
my_file = open("fin.txt","w")
#and then
my_file.write("hello")
my_file.close()

Python's equivalent to Ruby's File.read method

I'm trying to read the contents of a file in a single method call.
I don't want to have to worry about opening the file, reading from the file, and then closing the file (3 method calls).
I just want the content.
In ruby, there is File.read("/path/to/file"), which returns the contents of that file and properly closes it. Is there an equivalent in Python?
You can concatenate two instructions to get the same behaviour :/. But then the file isn't properly closed.
file = open("/path/to/file","r").read()
edit:
Best option as far as I know leaves you needing 2/3 you mention. Just use the with statement so you don't have to worry about closing said file.
with open("/path/to/file","r") as file:
text = file.read()
You can use a Context Manager in Python, which is available from Python 2.5.
with open('yourfile') as f:
contents = f.read()
It will automatically, open and close the file for you. The default mode is 'r' which stands for reading.
There is no such function included with Python. It's simple enough to define one, though.
def read_whole_file(path):
with open(path) as f:
return f.read()

Categories

Resources