Python提取.tgz指定目录文件报TypeError及代码优化咨询
问题解答
1. 报错原因与影响
你当前的代码存在核心逻辑位置错误:
- 类定义体中直接编写的3段
with tarfile.open(...)提取代码,会在类被Python解释器加载定义的阶段自动执行,不需要你手动调用类方法,这就是你看到文件被正常提取的原因——提取操作根本不是你写的img_skins.splash()这类调用语句触发的。 - 你定义的
splash/loading/centered是类的实例方法,按照Python语法规则,实例方法第一个参数默认接收类实例对象(通常命名为self),你将这个参数位命名为tf并用来接收tar对象,当你后续无参数调用img_skins.splash()时,自然会抛出缺少位置参数tf的错误。
这个报错必须处理,不存在“可以忽略”的说法:
- 代码执行逻辑完全错位,只要加载类就会自动执行提取,你完全无法控制提取时机,比如在其他文件导入这个类时,会直接触发解压操作,完全不符合预期。
- 代码重复打开3次压缩包,产生了不必要的磁盘IO开销,执行效率低。
- 类的封装作用完全失效,属于语法用对但逻辑完全错误的写法,后续修改配置很容易出bug。
2. 精简实现方案
三个提取逻辑的差异只有「压缩包内的源路径前缀」和「本地存储的目标目录」两个变量,完全不需要编写重复代码,也没必要生硬套用类结构。最优实现只需要打开一次压缩包、遍历一次压缩包内的文件成员,匹配到对应目标路径的文件直接解压到对应目录即可,代码简洁且执行效率更高:
import tarfile import os # 提取规则配置:格式为(压缩包内源目录前缀, 本地解压目标目录) EXTRACT_RULES = [ ("img/champion/splash/", r"Data\tar\new\splash"), ("img/champion/loading/", r"Data\tar\new\loading"), ("img/champion/centered/", r"Data\tar\new\centered"), ] def extract_target_imgs(tar_file_path): with tarfile.open(tar_file_path) as tar: for member in tar.getmembers(): # 匹配当前文件属于哪个目标提取目录 for src_prefix, dst_dir in EXTRACT_RULES: if member.path.startswith(src_prefix): # 替换解压路径,去掉压缩包内的前缀层级 member.path = os.path.join(dst_dir, member.path[len(src_prefix):]) tar.extract(member) break # 需要执行提取时直接调用函数即可,执行时机完全可控 extract_target_imgs(r"Data\tar\dragontail.tgz")
如果你确实有封装类的需求,也不要把执行逻辑直接写在类定义体中,参考如下写法即可:
import tarfile import os class ChampImgExtractor: TAR_PATH = r"Data\tar\dragontail.tgz" EXTRACT_RULES = [ ("img/champion/splash/", r"Data\tar\new\splash"), ("img/champion/loading/", r"Data\tar\new\loading"), ("img/champion/centered/", r"Data\tar\new\centered"), ] @classmethod def run(cls): with tarfile.open(cls.TAR_PATH) as tar: for member in tar.getmembers(): for src_prefix, dst_dir in cls.EXTRACT_RULES: if member.path.startswith(src_prefix): member.path = os.path.join(dst_dir, member.path[len(src_prefix):]) tar.extract(member) break # 调用方式 # ChampImgExtractor.run()
两种写法都避免了重复打开压缩包的问题,后续如果需要增减提取目录,只需要修改规则配置列表即可,不需要重复编写遍历、路径替换的逻辑。
内容的提问来源于stack exchange,提问作者Pendorax
相关产品推荐
相关产品推荐

