Python循环传入tar文件列表时tarfile解压报AttributeError
问题根本原因
核心错误是变量命名冲突导致导入的标准库模块被覆盖:
- 顶部通过
import tarfile导入压缩处理模块后,全局命名空间中tarfile本应指向该模块对象 - 后续遍历文件列表的for循环使用了
tarfile作为迭代变量名:for tarfile in tar_list:,循环启动后会将全局作用域的tarfile重新赋值为遍历得到的字符串类型文件路径,原本的模块引用被彻底覆盖 - 封装的
extract_fn函数内部调用tarfile.open()时,会从全局作用域查找tarfile变量,此时拿到的是字符串路径,字符串对象不存在open方法,因此抛出AttributeError: 'str' object has no attribute 'open'
这个逻辑完全匹配你观察到的现象:
- 单独调用
extract_fn时还未执行for循环,全局tarfile仍为模块对象,因此解压正常 - 函数内仅打印参数时不会调用
tarfile模块的方法,自然不会触发报错 - 给传入参数转字符串的操作没有解决全局模块被覆盖的问题,因此报错完全不变
修复方案
从根源规避命名冲突即可,推荐修改迭代变量名,不要和导入的模块、函数重名,同时可以优化资源释放逻辑避免句柄泄漏,修正后可运行的完整代码如下:
#!/usr/bin/python3 import tarfile import glob import os name = "myself" backup_path = "/tmp/test" # 原代码中db变量未定义,需提前赋值 db = "your_custom_db_name" # 推荐用os.path.join处理路径拼接,避免斜杠写错 tar_location = os.path.join(backup_path, db) tar_list = glob.glob(os.path.join(tar_location, "walfiles-*.tar.gz")) tar_destination = os.path.join(backup_path, "extracted") # 提前创建目标目录避免解压报错 os.makedirs(tar_destination, exist_ok=True) def extract_fn(tar_path, extract_dest): # 用with上下文管理器自动关闭文件,避免异常时资源泄漏 # 明确指定gz格式读取,避免自动检测格式的兼容问题 with tarfile.open(tar_path, "r:gz") as tar_obj: tar_obj.extractall(extract_dest) # 迭代变量改名为tar_path,不再和tarfile模块重名 for tar_path in tar_list: extract_fn(tar_path, tar_destination)
其他可选修复方式
如果不想修改迭代变量名,也可以在导入模块时给tarfile起别名,比如导入时写import tarfile as tar_lib,后续函数内统一用tar_lib.open()调用即可,但这种方式可读性不如直接修改冲突变量名,不推荐使用。
额外注意点
你之前测试时写的遍历代码中,将目标路径变量误写为wal_destination,和实际定义的tar_destination不一致,运行时会触发NameError,需要注意变量名拼写一致。
内容的提问来源于stack exchange,提问作者Anto
相关产品推荐
相关产品推荐

