Keep in mind that a object is for working with filesystem paths. Just like the built-in library of Python, there is an open method but no close in a Path object. Path
The is in the file handle that is returned by either the built-in open or by using the Path object's open method:.close
>>> from pathlib import Path
>>> p=Path(some_file)
>>> p
PosixPath('/tmp/file')
You can open that Path object either with the built-in open function or the open method in the Path object:
>>> fh=open(p) # open built-in function
>>> fh
<_io.TextIOWrapper name='/tmp/file' mode='r' encoding='UTF-8'>
>>> fh.close()
>>> fh=p.open() # Path open method which aliases to os.open
>>> fh
<_io.TextIOWrapper name='/tmp/file' mode='r' encoding='UTF-8'>
>>> fh.close()
You can have a look at the source code for pathlib on Github as an indication of how the authors of do it in their own code.pathlib
What I observe is one of three things.
The most common by far is to use :with
from pathlib import Path
p=Path('/tmp/file')
#create a file
with p.open(mode='w') as fi:
fi.write(f'Insides of: {str(p)}')
# read it back and test open or closed
with p.open(mode='r') as fi:
print(f'{fi.read()} closed?:{fi.closed}')
# prints 'Insides of: /tmp/file closed?:False'
As you likely know, at the end of the block the with methods are called. For a file, that means the file is closed. This is the most common approach in the __exit__ source code.pathlib
Second, you can also see in the source that a pathlib object maintains an entry and exit status and a flag of the file being open and closed. The functions is not explicitly called however. You can check that status with the os.close accessor. .closed
fh=p.open()
print(f'{fh.read()} closed?:{fh.closed}')
# prints Insides of: /tmp/file closed?:False
# fi will only be closed when fi goes out of scope...
# or you could (and should) do fh.close()
with p.open() as fi:
pass
print(f'closed?:{fi.closed}')
# fi still in scope but implicitly closed at the end of the with bloc
# prints closed?:True
Third, on cPython, files are closed when the file handle goes out of scope. This is not portable or considered 'good practice' to rely on, but commonly it is. There are instances of this in the pathlib source code.
The pathlib module offers an method that has a slightly different signature to the built-in open function. open
pathlib:
Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)
The built-in:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
In the case of this it has created a path p = pathlib.Path("temp/") so calling p with positional arguments (not using keywords) expects the first to be p.open("temp."+fn, "w", encoding ="utf-8"), then mode, and buffering expects an integer, and that is the essence of the error; an integer is expected but it received the string buffering. 'w'
This call is trying to open the path p.open("temp."+fn, "w", encoding ="utf-8") (which is a directory) and also providing a filename which isn't supported. You have to construct the full path, and then either call the path's open method or pass the full path into the open built-in function.p
Not really, as you can see in the pathlib module exist 2 types of path classes:
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 method, ie:open
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 method outside the context manager though:open
f = my_path.open("a")
f.write("...")
You're looking for the method , if my understanding is correct, whose documentation states:.absolute
>>> print(p.absolute.__doc__)
Return an absolute version of this path. This function works
even if the path doesn't point to anything.
No normalization is done, i.e. all '.' and '..' will be kept along.
Use resolve() to get the canonical path to a file.
With a test file on my system this returns:
>>> p = pathlib.Path('testfile')
>>> p.absolute()
PosixPath('/home/jim/testfile')
This method seems to be a new,
Created an issue to document this.