@@ -1760,6 +1760,8 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None,
1760
1760
# current position in the archive file
1761
1761
self .inodes = {} # dictionary caching the inodes of
1762
1762
# archive members already added
1763
+ self ._unames = {} # Cached mappings of uid -> uname
1764
+ self ._gnames = {} # Cached mappings of gid -> gname
1763
1765
1764
1766
try :
1765
1767
if self .mode == "r" :
@@ -2138,16 +2140,23 @@ def gettarinfo(self, name=None, arcname=None, fileobj=None):
2138
2140
tarinfo .mtime = statres .st_mtime
2139
2141
tarinfo .type = type
2140
2142
tarinfo .linkname = linkname
2143
+
2144
+ # Calls to pwd.getpwuid() and grp.getgrgid() tend to be expensive. To
2145
+ # speed things up, cache the resolved usernames and group names.
2141
2146
if pwd :
2142
- try :
2143
- tarinfo .uname = pwd .getpwuid (tarinfo .uid )[0 ]
2144
- except KeyError :
2145
- pass
2147
+ if tarinfo .uid not in self ._unames :
2148
+ try :
2149
+ self ._unames [tarinfo .uid ] = pwd .getpwuid (tarinfo .uid )[0 ]
2150
+ except KeyError :
2151
+ self ._unames [tarinfo .uid ] = ''
2152
+ tarinfo .uname = self ._unames [tarinfo .uid ]
2146
2153
if grp :
2147
- try :
2148
- tarinfo .gname = grp .getgrgid (tarinfo .gid )[0 ]
2149
- except KeyError :
2150
- pass
2154
+ if tarinfo .gid not in self ._gnames :
2155
+ try :
2156
+ self ._gnames [tarinfo .gid ] = grp .getgrgid (tarinfo .gid )[0 ]
2157
+ except KeyError :
2158
+ self ._gnames [tarinfo .gid ] = ''
2159
+ tarinfo .gname = self ._gnames [tarinfo .gid ]
2151
2160
2152
2161
if type in (CHRTYPE , BLKTYPE ):
2153
2162
if hasattr (os , "major" ) and hasattr (os , "minor" ):
0 commit comments