Skip to content
25 changes: 17 additions & 8 deletions Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,8 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None,
# current position in the archive file
self.inodes = {} # dictionary caching the inodes of
# archive members already added
self._unames = {} # Cached mappings of uid -> uname
self._gnames = {} # Cached mappings of gid -> gname

try:
if self.mode == "r":
Expand Down Expand Up @@ -2138,16 +2140,23 @@ def gettarinfo(self, name=None, arcname=None, fileobj=None):
tarinfo.mtime = statres.st_mtime
tarinfo.type = type
tarinfo.linkname = linkname

# Calls to pwd.getpwuid() and grp.getgrgid() tend to be expensive. To
# speed things up, cache the resolved usernames and group names.
if pwd:
try:
tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
except KeyError:
pass
if tarinfo.uid not in self._unames:
try:
self._unames[tarinfo.uid] = pwd.getpwuid(tarinfo.uid)[0]
except KeyError:
self._unames[tarinfo.uid] = ''
tarinfo.uname = self._unames[tarinfo.uid]
if grp:
try:
tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
except KeyError:
pass
if tarinfo.gid not in self._gnames:
try:
self._gnames[tarinfo.gid] = grp.getgrgid(tarinfo.gid)[0]
except KeyError:
self._gnames[tarinfo.gid] = ''
tarinfo.gname = self._gnames[tarinfo.gid]

if type in (CHRTYPE, BLKTYPE):
if hasattr(os, "major") and hasattr(os, "minor"):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improve the performance of :mod:`tarfile` when writing files, by caching user names
and group names.
Loading