Is it possible to define a variable as open("file.txt", "a") and call it more than once so you don't have to keep typing open("file.txt", "a")?
I tried, but it doesn't seem to work for me. I keep getting the error message:
ValueError: I/O operation on closed file.
My code looks like:
x = open("test.txt", "a")
with x as xfile:
xfile.write("hi")
#works fine until I try again later in the script
with x as yfile:
yfile.write("hello")
Question: Is there a way to do this that I'm missing?
(My apologies if this question is a repeat, I did search google and SO before I posted a new question.)
If you don't want to close the file right away, don't use a with statement and close it yourself when you're done.
outfile = open('test.txt', 'w')
outfile.write('hi\n')
x = 1
y = 2
z = x + y
outfile.write('hello\n')
outfile.close()
Typically you use the with statement when you want to open a file and do something with that file immediately, and then close it.
with open('test.txt', 'w') as xfile:
do something with xfile
However, it is best practice to take care of all your I/O with a single file at once if you can. So if you want to write several things to a file, put those things into a list, then write the contents of the list.
output = []
x = 1
y = 2
z = x + y
output.append(z)
a = 3
b = 4
c = a + b
output.append(c)
with open('output.txt', 'w') as outfile:
for item in output:
outfile.write(str(item) + '\n')
The with statement closes the file automatically. It is good to do everything related to the file inside the with statement (opening a file multiple times is also not a good idea).
with open("test.txt", "a") as xfile:
# do everything related to xfile here
But, if it doesn't solve your problem then don't use the with statement and close the file manually when the work related to that file is done.
From docs:
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 example doesn't make much sense without more context, but I am going to assume that you have a legitimate need to open the same file multiple times. Answering exactly what you are asking for, you can try this:
x = lambda:open("test.txt", "a")
with x() as xfile:
xfile.write("hi")
#works fine until I try again later in the script
with x() as yfile:
yfile.write("hello")
The usual way to use with statements (and indeed I think the only way they work) is with open("text.txt") as file:.
with statements are used for handling resources that need to be opened and closed.
with something as f:
# do stuff with f
# now you can no longer use f
is equivalent to:
f = something
try:
# do stuff with f
finally: # even if an exception occurs
# close f (call its __exit__ method)
# now you can no longer use f
Related
X = corpus.get("Andrew Shapiro")
testsite_array = []
with X as my_file:
for line in my_file:
testsite_array.append(line)
where corpus is a dictonary and Andrew Shapiro is an item in it. It gives me following error.
File "C:/Users/Vrushab PC/Downloads/Dissertation/untitled0.py", line 71, in <module>
with X as my_file:
AttributeError: __enter__
In order to use the with statement, the object, X in this case, the object must have implemented the enter method and exit method. The whole point is that it allow for the object to clean it's self up even in the case of an exception. Think try:except:finally done much more cleanly.
In order to answer your question though, I would need to know what you expected X to be. You named your temporary placeholder for it as my_file so is X supposed to be a file path that you want to open or something?
A full example of what you are attempting to do would be helpful.
Generally though, you would use the with statement for doing things like opening files like this:
with open(X, 'r') as my_file:
...
Tahoe
I find each time I open a file and read its content, it automatically close. So next time I have to open that file again to read it. I know this may be a good idea to reduce memory usage. But I need to consistently open a file due to my current task.
How should I do it?
This is my current way of reading a file
f = open('some_file', 'rU')
f.read()
After you do f.read(), the file doesn't close. In fact, it doesn't close unless you explicitly call f.close() or you use it in a with block like this:
with open('some_file') as f:
...
In which case, the file will be closed for you when the with block ends. It will also tend to be closed in any case when the file object has no more variables associated with it (ie, when f falls out of scope or gets reassigned), but this isn't guaranteed behaviour. If none of these things happen, the file is kept open.
The problem you are most likely seeing is that calling read again will get you an empty string. This doesn't happen because the file is closed - reading from a closed file gives you an error. Rather, files keep track of where you have read up to, so that if you only read part of it, you can then request the next part and it will start at the right place. To set it back to read from the start of the file again again, you can use the seek method:
with open('some_file') as f:
contents1 = f.read()
f.seek(0)
contents2 = f.read()
will give you contents1 and contents2 both containing the full contents of the file, rather than contents2 being empty. However, you probably don't want to do this unless the file could have changed in the meantime.
To make sure your file will consisently open or be consistently open, you need to be closing files or seek to 0.
while True:
f = open(...)
x = f.read()
print x
f.close()
or
f = open(...)
while True:
x = f.read()
print x
f.seek(0)
...unless you are going to write a one-liner, which will close automatically.
print open('some_file', 'rU').read()
This avoids any limit on the number of open files.
Additional thought: You can also use for line in open(...): pass, again as long as you remember to get to the beginning of the file one way or another.
Here's my code:
from random import random
f = open('Attractors1.txt', 'w')
for i in range(10):
theta = (3.14/2)*random()
f.write(str(theta))
I'm trying to create a list of 10 theta values so I can call them in another program, but I don't think the objects are writing correctly. How do I know if I'm doing it write? Whenever I run the code and execute f.read() I get an error saying the file isn't open.
You can't read from a file opened in write-only mode. :)
Since you're not writing within the loop, you'll only actually spit out a single number. Even if you fixed that, you'd get a bunch of numbers all in one line, because you're not adding newlines. .write isn't like print.
Also it's a good idea to use with when working with files, to ensure the file is closed when you think it should be.
So try this:
import math
from random import random
with open('Attractors1.txt', 'w') as f:
for i in range(10):
theta = (math.PI / 2) * random()
f.write("{0}\n".format(theta))
f = open('Attractors1.txt', 'w')
for i in range(10):
theta = (3.14/2)*random()
f.write(str(theta))
f.close()
Then to read:
f = open('Attractors1.txt','r')
text = f.read()
print text
Edit: wups beaten to it
For some reason after my for loops I am not able to read the ouput text file.
For example :
for line in a:
name = (x)
f = open('name','w')
for line in b:
get = (something)
f.write(get)
for line in c:
get2 = (something2)
f.write(get2)
(the below works if the above is commented out only)
f1 = open(name, 'r')
for line in f1:
print line
If I comment out the loops, I am able to read the file and print the contents.
I am very new to coding and guessing this is something obvious that I am missing.However I can't seem to figure it out. I have used google but the more I read the more I feel I am missing something. Any advice is appreciated.
#bernie is right in his comment above. The problem is that when you do open(..., 'w'), the file is rewritten to be blank, but Python/the OS doesn't actually write out the things you write to disk until its buffer is filled up or you call close(). (This delay helps speed things up, because writing to disk is slow.) You can also call flush() to force this without closing the file.
The with statement bernie referred to would look like this:
with open('name', 'w') as f:
for line in b:
b.write(...)
for line in c:
b.write(...)
# f is closed now that we're leaving the with block
# and any writes are actually written out to the file
with open('name', 'r') as f:
for line in f:
print line
If you're using Python 2.5 rather than 2.6 or 2.7, you'll have to do from __future__ import with_statement at the top of your file.
I'm using the CSV module to read a tab delimited file. Code below:
z = csv.reader(open('/home/rv/ncbi-blast-2.2.23+/db/output.blast'), delimiter='\t')
But when I add Z.close() to end of my script i get and error stating "csv.reader' object has no attribute 'close'"
z.close()
So how do i close "Z"?
The reader is really just a parser. When you ask it for a line of data, it delegates the reading action to the underlying file object and just converts the result into a set of fields. The reader itself doesn't manage any resources that would need to be cleaned up when you're done using it, so there's no need to close it; it'd be a meaningless operation.
You should make sure to close the underlying file object, though, because that does manage a resource (an open file descriptor) that needs to be cleaned up. Here's the way to do that:
with open('/home/rv/ncbi-blast-2.2.23+/db/output.blast') as f:
z = csv.reader(f, delimiter='\t')
# do whatever you need to with z
If you're not familiar with the with statement, it's roughly equivalent to enclosing its contents in a try...finally block that closes the file in the finally part.
Hopefully this doesn't matter (and if it does, you really need to update to a newer version of Python), but the with statement was introduced in Python 2.5, and in that version you would have needed a __future__ import to enable it. If you were working with an even older version of Python, you would have had to do the closing yourself using try...finally.
Thanks to Jared for pointing out compatibility issues with the with statement.
You do not close CSV readers directly; instead you should close whatever file-like object is being used. For example, in your case, you'd say:
f = open('/home/rv/ncbi-blast-2.2.23+/db/output.blast')
z = csv.reader(f, delimiter='\t')
...
f.close()
If you are using a recent version of Python, you can use the with statement, e.g.
with open('/home/rv/ncbi-blast-2.2.23+/db/output.blast') as f:
z = csv.reader(f, delimiter='\t')
...
This has the advantage that f will be closed even if you throw an exception or otherwise return inside the with-block, whereas such a case would lead to the file remaining open in the previous example. In other words, it's basically equivalent to a try/finally block, e.g.
f = open('/home/rv/ncbi-blast-2.2.23+/db/output.blast')
try:
z = csv.reader(f, delimiter='\t')
...
finally:
f.close()
You don't close the result of the reader() method, you close the result of the open() method. So, use two statements: foo=open(...); bar=csv.reader(foo). Then you can call foo.close().
There are no bonus points awarded for doing in one line that which can be more readable and functional in two.