bpo-41092: Request actual filesize from 'os.path.getsize'

Provide the ability to get the actual, on-disk size of a file using
'os.path.getsize'. This is helpful when dealing with things like sparse
files.

Signed-off-by: Stephen Finucane <stephen@that.guru>
This commit is contained in:
Stephen Finucane 2020-06-23 16:45:46 +00:00
parent 261cfedf76
commit 842c72ebda
3 changed files with 34 additions and 5 deletions

View File

@ -234,14 +234,22 @@ the :mod:`glob` module.)
Accepts a :term:`path-like object`.
.. function:: getsize(path)
.. function:: getsize(path, apparent=True)
Return the size, in bytes, of *path*. Raise :exc:`OSError` if the file does
not exist or is inaccessible.
not exist or is inaccessible. If *apparent* is ``True``, the apparent size
(number of bytes) of the file is returned. If ``False``, the actual size
(disk space occupied) is returned. The actual size reflects the block size,
meaning it will typically be larger than the apparent size. However, the
inverse may also be true due to holes in ("sparse") files, internal
fragmentation, indirect blocks, etc.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. versionchanged:: 3.10
Add the optional *apparent* parameter.
.. function:: isabs(path)

View File

@ -45,9 +45,20 @@ def isdir(s):
return stat.S_ISDIR(st.st_mode)
def getsize(filename):
"""Return the size of a file, reported by os.stat()."""
return os.stat(filename).st_size
def getsize(filename, apparent=True):
"""Return the size of a file, reported by os.stat().
If 'apparent' is True (default), the apparent size (number of bytes) of the
file is returned. If False, the actual size (disk space occupied) is
returned. The actual size reflects the block size, meaning it will
typically be larger than the apparent size. However, the inverse may also
be true due to holes in ("sparse") files, internal fragmentation, indirect
blocks, etc.
"""
if apparent:
return os.stat(filename).st_size
else:
return os.stat(filename).st_blocks * 512
def getmtime(filename):

View File

@ -102,10 +102,20 @@ class GenericTest:
create_file(filename, b'Hello')
self.assertEqual(self.pathmodule.getsize(filename), 5)
self.assertEqual(
self.pathmodule.getsize(filename, apparent=False), 4096)
os.remove(filename)
create_file(filename, b'Hello World!')
self.assertEqual(self.pathmodule.getsize(filename), 12)
self.assertEqual(
self.pathmodule.getsize(filename, apparent=False), 4096)
os.remove(filename)
open(filename, 'xb', 0).close()
os.truncate(filename, 512)
self.assertEqual(self.pathmodule.getsize(filename), 512)
self.assertEqual(self.pathmodule.getsize(filename, apparent=False), 0)
def test_filetime(self):
filename = support.TESTFN