Skip to content

Commit 842c72e

Browse files
committed
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>
1 parent 261cfed commit 842c72e

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

Doc/library/os.path.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,22 @@ the :mod:`glob` module.)
234234
Accepts a :term:`path-like object`.
235235

236236

237-
.. function:: getsize(path)
237+
.. function:: getsize(path, apparent=True)
238238

239239
Return the size, in bytes, of *path*. Raise :exc:`OSError` if the file does
240-
not exist or is inaccessible.
240+
not exist or is inaccessible. If *apparent* is ``True``, the apparent size
241+
(number of bytes) of the file is returned. If ``False``, the actual size
242+
(disk space occupied) is returned. The actual size reflects the block size,
243+
meaning it will typically be larger than the apparent size. However, the
244+
inverse may also be true due to holes in ("sparse") files, internal
245+
fragmentation, indirect blocks, etc.
241246

242247
.. versionchanged:: 3.6
243248
Accepts a :term:`path-like object`.
244249

250+
.. versionchanged:: 3.10
251+
Add the optional *apparent* parameter.
252+
245253

246254
.. function:: isabs(path)
247255

Lib/genericpath.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,20 @@ def isdir(s):
4545
return stat.S_ISDIR(st.st_mode)
4646

4747

48-
def getsize(filename):
49-
"""Return the size of a file, reported by os.stat()."""
50-
return os.stat(filename).st_size
48+
def getsize(filename, apparent=True):
49+
"""Return the size of a file, reported by os.stat().
50+
51+
If 'apparent' is True (default), the apparent size (number of bytes) of the
52+
file is returned. If False, the actual size (disk space occupied) is
53+
returned. The actual size reflects the block size, meaning it will
54+
typically be larger than the apparent size. However, the inverse may also
55+
be true due to holes in ("sparse") files, internal fragmentation, indirect
56+
blocks, etc.
57+
"""
58+
if apparent:
59+
return os.stat(filename).st_size
60+
else:
61+
return os.stat(filename).st_blocks * 512
5162

5263

5364
def getmtime(filename):

Lib/test/test_genericpath.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,20 @@ def test_getsize(self):
102102

103103
create_file(filename, b'Hello')
104104
self.assertEqual(self.pathmodule.getsize(filename), 5)
105+
self.assertEqual(
106+
self.pathmodule.getsize(filename, apparent=False), 4096)
105107
os.remove(filename)
106108

107109
create_file(filename, b'Hello World!')
108110
self.assertEqual(self.pathmodule.getsize(filename), 12)
111+
self.assertEqual(
112+
self.pathmodule.getsize(filename, apparent=False), 4096)
113+
os.remove(filename)
114+
115+
open(filename, 'xb', 0).close()
116+
os.truncate(filename, 512)
117+
self.assertEqual(self.pathmodule.getsize(filename), 512)
118+
self.assertEqual(self.pathmodule.getsize(filename, apparent=False), 0)
109119

110120
def test_filetime(self):
111121
filename = support.TESTFN

0 commit comments

Comments
 (0)