pathlib Path `write_text` in append mode

Question:

Is there a shortcut for python pathlib.Path objects to write_text() in append mode?

The standard open() function has mode="a" to open a file for writing and appending to the file if that file exists, and a Paths .open() function seems to have the same functionality (my_path.open("a")).

But what about the handy .write_text('..') shortcut, is there a way to use pathlib to open and append to a file with just doing the same things as with open()?

For clarity, I can do

with my_path.open('a') as fp:
    fp.write('my text')

but is there another way?

my_path.write_text('my text', mode='a')

Asked By: danodonovan

||

Answers:

Not really, as you can see in the pathlib module exist 2 types of path classes:

  • pure path classes {PurePath, PurePosixPath, PureWindowsPath}
  • concrete path classes {Path, PosixPath, WindowsPath}.

Parameters of theses classes constructors will be just *pathsegments.

And if you look at the available read/write methods (read_text/read_bytes and write_text/write_bytes) you’ll also see mode won’t be available neither

So, as you’ve already discovered, the only way you can use mode with these pathlib classes is by using open method, ie:

with my_path.open("a") as f:
    f.write("...")

This is by design and that way the pathlib classes have become really “clean”. Also, the above snippet is already canonical so it can’t be simplified any further. You could use open method outside the context manager though:

f = my_path.open("a")
f.write("...")
Answered By: BPL

The pathlib methods Path().write_text() and Path().write_bytes() close the file connection on exit.

from pathlib import Path

Path('file.txt').write_text('my text')
Path('file1.txt').write_bytes(b'my text')

Using append mode i.e open('a', ...) will instanciate a TextIOWrapper which is also closed by write_text / write_bytes on exit.

f = Path('file.txt')
f.open("a")
f.write_text('my text')
# or
f.write_bytes(b'my text')

Otherwise must close it manually

f = Path('file1.txt').open('a')
f.write('my text')
f.close()

but can be this way:

fp = Path('test.txt').open('a')
<_io.TextIOWrapper name='test.txt' mode='a' encoding='UTF-8'>
fp.write('my text')

fq = Path('test1.txt').open('ab', encoding='iso8859-1')
<_io.TextIOWrapper name='test1.txt' mode='a' encoding='iso8859-1'>
fq.write(b'my text')
Answered By: britodfbr

If its just too much trouble to use the WITH structure, this might provide a sort of work around:

from pathlib import Path as p
t1 = "The quick brown fox" 
t2 = "just jumped over the fence"
t3 = "to greet the lazy poodle."
mypath = p("D:Try_this")
myfile = p("fox.txt")
if not(mypath.is_dir()):
    mypath.mkdir()
wholepath = p(mypath / myfile)
wholepath.write_text("n".join([t1,t2,t3]))
Answered By: BigDaddy

There is no "append mode" for write_text, nor is there a corresponding append_text method. If you need it, you can write a function for it yourself pretty easily:

def append_text(path, text, encoding=None, errors=None):
   with path.open("a", encoding=encoding, errors=errors) as f:
       f.write(text)

You might be wondering why such a thing isn’t built directly into pathlib as a method. One reason is precisely because it is so easy to implement yourself that it’s not really worth adding, but clearly that’s not the whole story, because read_text and write_text would be similarly easy to implement yourself.

I think a major reason why pathlib.Path objects don’t (and, indeed, shouldn’t) have a append_text method is because it creates a hole for inexperienced users to fall into, which is a huge sin in API design.

Specifically, the hole I’m referring to is using append_text on the same file repeatedly in a loop. Because you’re continually opening and closing the file, it is slow. Plus, doing so many unnecessary writes is probably not great for the health of your hard drive.

Worse, because the program will actually behave correctly (e.g. the file will have the contents they intended), they may not even notice anything is wrong, because they don’t necessarily have a mental gauge on how long writing to a file "should" take.

This is exactly the sort of code a naïve programmer would write:

from pathlib import Path

N = 100

path = Path("numbers.txt")

path.write_text(f"{N}n")
for i in range(N):
    path.append_text(f"{i}n")
Answered By: Kevin
  • Is it a nice solution? No
  • Is it memory efficient? No
  • Is it a one-liner? Yes
from pathlib import Path

my_path = Path('/shopping_list.txt')

my_str = 'nFresh SpinachnFrozen Strawberries'

my_str.write_text(my_path.read_text() + my_str)
Answered By: DannyDannyDanny

Create a function and bind to pathlib.Path

from pathlib import PosixPath
from pathlib import Path as p

def _append_text(self:PosixPath, target:str) -> None:
    with self.open('a') as f:
        f.write(target)

p.append_text = _append_text
Path = p

Create a new path object

sample_text = Path('/tmp/sample.txt')

Write mode

sample_text.write_text('hello world')

Append mode

sample_text.append_text('hello world, appended!')
Answered By: sinestandly
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.