How do I write a line to a file in modern Python? I heard that this is deprecated:
print >>f, "hi there"
Also, does "\n"
work on all platforms, or should I use "\r\n"
on Windows?
This should be as simple as:
with open('somefile.txt', 'a') as the_file:
the_file.write('Hello\n')
From The Documentation:
Do not use os.linesep as a line terminator when writing files opened in text mode (the default); use a single '\n' instead, on all platforms.
Some useful reading:
The with statement
open() 'a' is for append, or use 'w' to write with truncation
'a' is for append, or use
'w' to write with truncation
os (particularly os.linesep)
You should use the print()
function which is available since Python 2.6+
from __future__ import print_function # Only needed for Python 2
print("hi there", file=f)
For Python 3 you don't need the import
, since the print()
function is the default.
The alternative would be to use:
f = open('myfile', 'w')
f.write('hi there\n') # python will convert \n to os.linesep
f.close() # you can omit in most cases as the destructor will call it
Quoting from Python documentation regarding newlines:
On output, if newline is None, any '\n' characters written are translated to the system default line separator, os.linesep. If newline is '', no translation takes place. If newline is any of the other legal values, any '\n' characters written are translated to the given string.
\n
" would require newline="" otherwise you'd get \r\r\n
on Windows. There is no reason to futz about with os.linesep at all.
\r\n
which contains \n
which is translated to os.linesep which is \r\n
so the end result is \r\r\n
.
open('myfile','a')
instead open('myfile','w')
?
The python docs recommend this way:
with open('file_to_write', 'w') as f:
f.write('file contents\n')
So this is the way I usually do it :)
Statement from docs.python.org:
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. It is also much shorter than writing equivalent try-finally blocks.
with
inside a loop. That makes me constantly open and close the file as I proceed in my loop. Maybe I am missing something here, or this is really a disadvantage in this particular scenario?
Regarding os.linesep:
Here is an exact unedited Python 2.7.1 interpreter session on Windows:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.linesep
'\r\n'
>>> f = open('myfile','w')
>>> f.write('hi there\n')
>>> f.write('hi there' + os.linesep) # same result as previous line ?????????
>>> f.close()
>>> open('myfile', 'rb').read()
'hi there\r\nhi there\r\r\n'
>>>
On Windows:
As expected, os.linesep does NOT produce the same outcome as '\n'
. There is no way that it could produce the same outcome. 'hi there' + os.linesep
is equivalent to 'hi there\r\n'
, which is NOT equivalent to 'hi there\n'
.
It's this simple: use \n
which will be translated automatically to os.linesep. And it's been that simple ever since the first port of Python to Windows.
There is no point in using os.linesep on non-Windows systems, and it produces wrong results on Windows.
DO NOT USE os.linesep!
os.linesep
in Windows in text mode, the outcome is \r\r\n
which is wrong. "Windows uses ..." is meaningless. The C runtime library (and hence Python) translate \n
to \r\n
on output in text mode. Other software may behave differently. It is NOT the case that all software running on Windows recognises a lone \n
as a line separator when reading in text mode. Python does. Microsoft's Notepad text editor doesn't.
\r
...
os.linesep
is "wrong" here. Its like Department of Redundancy Department
. Yes you can do it. No, you don't want to.
I do not think there is a "correct" way.
I would use:
with open ('myfile', 'a') as f: f.write ('hi there\n')
In memoriam Tim Toady.
with
goes out of scope.
zen of perl
would be a bit of an oxymoron.
In Python 3 it is a function, but in Python 2 you can add this to the top of the source file:
from __future__ import print_function
Then you do
print("hi there", file=f)
If you are writing a lot of data and speed is a concern you should probably go with f.write(...)
. I did a quick speed comparison and it was considerably faster than print(..., file=f)
when performing a large number of writes.
import time
start = start = time.time()
with open("test.txt", 'w') as f:
for i in range(10000000):
# print('This is a speed test', file=f)
# f.write('This is a speed test\n')
end = time.time()
print(end - start)
On average write
finished in 2.45s on my machine, whereas print
took about 4 times as long (9.76s). That being said, in most real-world scenarios this will not be an issue.
If you choose to go with print(..., file=f)
you will probably find that you'll want to suppress the newline from time to time, or replace it with something else. This can be done by setting the optional end
parameter, e.g.;
with open("test", 'w') as f:
print('Foo1,', file=f, end='')
print('Foo2,', file=f, end='')
print('Foo3', file=f)
Whichever way you choose I'd suggest using with
since it makes the code much easier to read.
Update: This difference in performance is explained by the fact that write
is highly buffered and returns before any writes to disk actually take place (see this answer), whereas print
(probably) uses line buffering. A simple test for this would be to check performance for long writes as well, where the disadvantages (in terms of speed) for line buffering would be less pronounced.
start = start = time.time()
long_line = 'This is a speed test' * 100
with open("test.txt", 'w') as f:
for i in range(1000000):
# print(long_line, file=f)
# f.write(long_line + '\n')
end = time.time()
print(end - start, "s")
The performance difference now becomes much less pronounced, with an average time of 2.20s for write
and 3.10s for print
. If you need to concatenate a bunch of strings to get this loooong line performance will suffer, so use-cases where print
would be more efficient are a bit rare.
print()
multiple times for each line, you can input each line as a positional argument and specify a newline delimiter using print(line1, line2, ... sep="\n")
. This makes only one write call.
Since 3.5 you can also use the pathlib
for that purpose:
Path.write_text(data, encoding=None, errors=None) Open the file pointed to in text mode, write data to it, and close the file:
import pathlib
pathlib.Path('textfile.txt').write_text('content')
When you said Line it means some serialized characters which are ended to '\n' characters. Line should be last at some point so we should consider '\n' at the end of each line. Here is solution:
with open('YOURFILE.txt', 'a') as the_file:
the_file.write("Hello")
in append mode after each write the cursor move to new line, if you want to use w
mode you should add \n
characters at the end of the write()
function:
the_file.write("Hello\n")
One can also use the io
module as in:
import io
my_string = "hi there"
with io.open("output_file.txt", mode='w', encoding='utf-8') as f:
f.write(my_string)
If you want to avoid using write()
or writelines()
and joining the strings with a newline yourself, you can pass all of your lines to print()
, and the newline delimiter and your file handle as keyword arguments. This snippet assumes your strings do not have trailing newlines.
print(line1, line2, sep="\n", file=f)
You don't need to put a special newline character is needed at the end, because print()
does that for you.
If you have an arbitrary number of lines in a list, you can use list expansion to pass them all to print()
.
lines = ["The Quick Brown Fox", "Lorem Ipsum"]
print(*lines, sep="\n", file=f)
It is OK to use "\n"
as the separator on Windows, because print()
will also automatically convert it to a Windows CRLF newline ("\r\n"
).
If you want to insert items in a list with a format per line, a way to start could be:
with open('somefile.txt', 'a') as the_file:
for item in items:
the_file.write(f"{item}\n")
To write text in a file in the flask can be used:
filehandle = open("text.txt", "w")
filebuffer = ["hi","welcome","yes yes welcome"]
filehandle.writelines(filebuffer)
filehandle.close()
with open('file_to_write', 'w') as f:
statement. It's much easier to make sure that file will not be left open if someone accidentally wrote something in between that would result in not having an explicit close()
call
You can also try filewriter
pip install filewriter
from filewriter import Writer
Writer(filename='my_file', ext='txt') << ["row 1 hi there", "row 2"]
Writes into my_file.txt
Takes an iterable or an object with __str__
support.
When I need to write new lines a lot, I define a lambda that uses a print
function:
out = open(file_name, 'w')
fwl = lambda *x, **y: print(*x, **y, file=out) # FileWriteLine
fwl('Hi')
This approach has the benefit that it can utilize all the features that are available with the print
function.
Update: As is mentioned by Georgy in the comment section, it is possible to improve this idea further with the partial
function:
from functools import partial
fwl = partial(print, file=out)
IMHO, this is a more functional and less cryptic approach.
from functools import partial; fwl = partial(print, file=out)
.
A very basic way to write lines in python to a text file. This will overwrite a file with the same name if exist.
%%writefile test.txt
i am writing this to test.txt file \n
writing this line also
since others have answered how to do it, I'll answer how it happens line by line.
with FileOpenerCM('file.txt') as fp: # is equal to "with open('file.txt') as fp:"
fp.write('dummy text')
this is a so-called context manager
, anything that comes with a with
block is a context manager. so let's see how this happens under the hood.
class FileOpenerCM:
def __init__(self, file, mode='w'):
self.file = open(file, mode)
def __enter__(self):
return self.file
def __exit__(self, exc_type, exc_value, exc_traceback):
self.file.close()
the first method __init__
is (as you all know) the initialization method of an object. whenever an object is created obj.__init__
is definitely called. and that's the place where you put your all the init kinda code.
the second method __enter__
is a bit interesting. some of you might not have seen it because it is a specific method for context managers. what it returns is the value to be assigned to the variable after the as
keyword. in our case, fp
.
the last method is the method to run after an error is captured or if the code exits the with block. exc_type
, exc_value
, exc_traceback
variables are the variables that hold the values of the errors that occurred inside with block. for example,
exc_type: TypeError
exc_value: unsupported operand type(s) for +: 'int' and 'str
exc_traceback: <traceback object at 0x6af8ee10bc4d>
from the first two variables, you can get info enough info about the error. honestly, I don't know the use of the third variable, but for me, the first two are enough. if you want to do more research on context managers surely you can do it and note that writing classes are not the only way to write context managers. with contextlib you can write context managers through functions(actually generators) as well. it's totally up to you to have a look at it. you can surely try generator functions with contextlib but as I see classes are much cleaner.
Success story sharing
with
is a safer way to remember to close a file.the_file.close()
?