Writing and reading at the same time in Python? - python

I'm a total beginner in Python. I've been trying to shorten the #1 version (which works fine) to a cleaner code and I thought I could just squeeze it into a one-liner. Why doesn't the #2 work?
I'm getting the "NoneType" object has no attribute 'seek' when I try to run it.
from sys import argv
script, filename = argv
# 1
open_file = open(filename, 'w+')
open_file.write("Hello world!")
open_file.seek(0)
print open_file.read()
# 2
open_file = open(filename, 'w+').write("Hello world!").seek(0).read()
print open_file
I have tried numerous ways but I still can't get it to work.
Thanks a lot!

From the documentation:
write(b):
Write the given bytes-like object, b, to the underlying raw stream, and return the number of bytes written
So, it returns the number of bytes written, not a file object, so you cannot chain another call after the write(). Note you also cannot chain seek() as that returns an offset into the file.

The reason why a one-liner is not working, is because .write() does not return back the original file descriptor. Instead, write() returns the number of characters/bytes (depending on the opened file mode) that have been written.
Unfortunatelly I don't think there's a way to do what you want in one go, that would not sacrifice readability. What you could do is wrap your code into a function, or write your own file-like object that would immediatelly seek after write.

For writing,
with open(filename, 'w+') as f: f.write("Hello world!")
and to print content
with open(filename, 'r+') as f: print(f.read())
works for me! Nonetype error is because of no return type as pointed out by others.

You are getting NoneType because file.write function return None. Or in this case int (How many bytes it has write on the file)

You must close the file before you open again it. open_file.close()

Related

Save integer to file and retrieve it

myFile = open('high scores.py', 'w')
if player1_total > player2_total :
myFile.write(player1_total)
else :
myFile.write(player2_total)
myFile.close
The file write method only expects strings (or bytestrings, if the file is open in binary mode). The max function can save you a conditional, too. Try something like:
with open('high_scores.py', 'w') as myFile:
myFile.write(str(max(player1_total, player2_total)))
You would then be able to read this back with
with open('high_scores.py') as f:
high_score = int(f.read())
Note that the use of the with statements ensures that files are always correctly closed no matter what the outcome of the with block.
Personally, since the file isn't a Python program file I'd use a different extension in its name. For storing a larger set of values consider using the shelve module.
myFile = open('high scores.py', 'w')
if player1_total > player2_total :
myFile.write(str(player1_total))
else :
myFile.write(str(player2_total))
myFile.close()
The issue is that you need to cast the integer to string before writing. easiest way is str(player2_total)
Also close the file once done documentation
When you’re done with a file, call f.close() to close it and free up
any system resources taken up by the open file.
But a concise way to write it is give in this answer.
More info on using the context manager with open(): can be found in PEP-0343 & read up on this blog post as well
cast your values to strings before writing to file:
myFile.write(str(player1_total))

File close error, [AttributeError: 'int' object has no attribute 'close'] when reducing file write code to a single line

Going through Zed Shaw's book Exercise 17 [about copying one file to another] where he reduces his these two lines of code
in_file = open(from_file)
indata = in_file.read()
into one as :
indata = open(from_file).read()
there's also a piece of code where he writes
out_file = open(to_file, 'w')
out_file.write(indata)
So I was reducing this into one line same as above :
out_file = open(to_file, 'w').write(indata)
This seems to work fine but when I close the out_file there's an error as:
Traceback (most recent call last):
File "filesCopy.py", line 27, in <module>
out_file.close()
AttributeError: 'int' object has no attribute 'close'
I am unable to grasp what is going on and how close() is working here?
The two are not equivalent. If you write out_file = open(to_file, 'w').write(indata), you have implicitly written:
# equivalent to second code sample
temp = open(to_file, 'w')
out_file = temp.write(indata)
Now as we can see in the documentation of write():
f.write(string) writes the contents of string to the file, returning the number of characters written.
So it returns an integer. So in your second sample out_file is not a file handler, but an integer. Further in the code, you somewhere aim to close the out_file file handler with out_file.close(). But since out_file is no longer a file handler, it thus makes no sense to call close on this.
Nevertheless, by using a context, you do no longer need to perform a .close() yourself, so more elegantly is probably:
with open(to_file, 'w') as out_file:
out_file.write(indata)
The reduction in the book itself is allowed (well at least semantically, it is better to use context manager), since the author probably never closes the file handle explicitly.
Following is usually better approach, both for reading & writing:
with open("myfile.txt", "w") as f:
# do something with f
There is no need to close f with this code.
With code val = open(to_file, 'w').write(indata) "val" will be return value of write function, not open function.
The write method returns the number of characters written in your file which is an integer not a file object and therefore doesn't have a close method.
In [6]: a = open('test', 'w')
In [7]: t = a.write('ssss')
In [8]: t
Out[8]: 4
Also, calling the I/O methods directly on open() is recommended only if you don't want to have any further interaction with the file. Besides, the most proper way to deal with file objects is to use a with statement that closes the file automatically at the end of the block and there's no need to call the close() manually.
with open('filename', 'w') as f:
# do something
The read() function reads the file and then returns the file content, so when you assign indata to read() it's assigning the returned file content. The difference is that the write() function returns the number of characters written, therefore your outdata is now an int object.
Read more about it here: https://docs.python.org/3.6/tutorial/inputoutput.html
Therefore, you cannot combine the write() function into one line and expect to have a referenced file object to close after, and that's disastrous.
The preferred way is to use the with block. Refer to #Willem's answer for more details.
The author "Zed" has already clarified when you will read the page 64 from that book. Please read below:
When I try to make this script shorter, I get an error when I close the files at the end.
You probably did something like this, indata = open(from_file).read(), which means you don’t need to then do in_file.close() when you reach the end of the script. It should already be closed by Python once that one line runs.

Use of python close command (LPTHW ex 17 extra credit) [duplicate]

I am having a great time trying to figure out why there doesn't need to be a closing attribute for this few lines of code I wrote:
from sys import argv
from os.path import exists
script, from_file, to_file = argv
file_content = open(from_file).read()
new_file = open(to_file, 'w').write(file_content)
new_file.close()
file_content.close()
I read some things and other people's posts about this, but their scripts were a lot more complicated than what I'm currently learning, so I couldn't figure out why.
I am doing Learning Python the Hard Way and would appreciate any help.
file_content is a string variable, which contains contents of the file -- it has no relation to the file. The file descriptor you open with open(from_file) will be closed automatically: file sessions are closed after the file-objects exit the scope (in this case, immediately after .read()).
open(...) returns a reference to a file object, calling read on that reads the file returning a string object, calling write writes to it returning None, neither of which have a close attribute.
>>> help(open)
Help on built-in function open in module __builtin__:
open(...)
open(name[, mode[, buffering]]) -> file object
Open a file using the file() type, returns a file object. This is the
preferred way to open a file.
>>> a = open('a', 'w')
>>> help(a.read)
read(...)
read([size]) -> read at most size bytes, returned as a string.
If the size argument is negative or omitted, read until EOF is reached.
Notice that when in non-blocking mode, less data than what was requested
may be returned, even if no size parameter was given.
>>> help(a.write)
Help on built-in function write:
write(...)
write(str) -> None. Write string str to file.
Note that due to buffering, flush() or close() may be needed before
the file on disk reflects the data written.
Theres a couple ways of remedying this:
>>> file = open(from_file)
>>> content = file.read()
>>> file.close()
or with python >= 2.5
>>> with open(from_file) as f:
... content = f.read()
The with will make sure the file is closed.
When you do file_content = open(from_file).read(), you set file_content to the contents of the file (as read by read). You can't close this string. You need to save the file object separately from its contents, something like:
theFile = open(from_file)
file_content = theFile.read()
# do whatever you need to do
theFile.close()
You have a similar problem with new_file. You should separate the open(to_file) call from the write.

What is causing this error and how can I fix it?

I am trying to make a simple compression program in Python, but am receiving this error
with open("admin.dll", "r").read() as text:
AttributeError: __exit__
Why am I getting this error? This is my full code
import zlib, sys, time, base64
with open("admin.txt", "r").read() as file:
print("Uncompressed: " + str(sys.getsizeof(file)))
compressed = zlib.compress(file, 9)
print("Compressed: ", end="")
print(sys.getsizeof(compressed))
You are asking Python to treat the result of the expression open("admin.dll", "r").read() (a string) as a context manager. Context managers are expected to have a __exit__ method, but strings don't have those methods.
You'd normally pass in the file object:
with open("admin.dll", "r") as fileobj:
text = fileobj.read()
File objects do have the required context manager methods.
Note that you have other errors too; sys.getsizeof produces the memory size of a Python object, not the size of a file. You could use os.stat() for that, or seek to the end of the file and use fileobj.tell() to get a size. To get the size of the compressed result, use len().
I believe you should open the file. Appoint a variable to it. In your case file.
Then on the next line you can read the file by calling f.read()

Python - 'str' object has no attribute 'close'

I am having a great time trying to figure out why there doesn't need to be a closing attribute for this few lines of code I wrote:
from sys import argv
from os.path import exists
script, from_file, to_file = argv
file_content = open(from_file).read()
new_file = open(to_file, 'w').write(file_content)
new_file.close()
file_content.close()
I read some things and other people's posts about this, but their scripts were a lot more complicated than what I'm currently learning, so I couldn't figure out why.
I am doing Learning Python the Hard Way and would appreciate any help.
file_content is a string variable, which contains contents of the file -- it has no relation to the file. The file descriptor you open with open(from_file) will be closed automatically: file sessions are closed after the file-objects exit the scope (in this case, immediately after .read()).
open(...) returns a reference to a file object, calling read on that reads the file returning a string object, calling write writes to it returning None, neither of which have a close attribute.
>>> help(open)
Help on built-in function open in module __builtin__:
open(...)
open(name[, mode[, buffering]]) -> file object
Open a file using the file() type, returns a file object. This is the
preferred way to open a file.
>>> a = open('a', 'w')
>>> help(a.read)
read(...)
read([size]) -> read at most size bytes, returned as a string.
If the size argument is negative or omitted, read until EOF is reached.
Notice that when in non-blocking mode, less data than what was requested
may be returned, even if no size parameter was given.
>>> help(a.write)
Help on built-in function write:
write(...)
write(str) -> None. Write string str to file.
Note that due to buffering, flush() or close() may be needed before
the file on disk reflects the data written.
Theres a couple ways of remedying this:
>>> file = open(from_file)
>>> content = file.read()
>>> file.close()
or with python >= 2.5
>>> with open(from_file) as f:
... content = f.read()
The with will make sure the file is closed.
When you do file_content = open(from_file).read(), you set file_content to the contents of the file (as read by read). You can't close this string. You need to save the file object separately from its contents, something like:
theFile = open(from_file)
file_content = theFile.read()
# do whatever you need to do
theFile.close()
You have a similar problem with new_file. You should separate the open(to_file) call from the write.

Categories