Python脚本用argparse传时间参数重构时S3桶对象匹配异常求助
问题根因
- 核心函数残留硬编码sys.argv读取逻辑:
get_file()、convert_index()没有接入argparse解析出的参数值,仍在按固定索引读取sys.argv[2]/sys.argv[3]/sys.argv[5],参数值完全和解析出的args对象脱节 - 时间判断表达式存在语法逻辑错误:原判断行
end.startswith(start_time) == start_time属于无效写法——str.startswith()返回布尔值,永远不可能和字符串类型的时间参数相等,是硬编码时代凑出的临时可用写法,参数传入值变动后直接触发异常 - 参数空值防护缺失:argparse将index、start_time、end_time全部设为非必填,用户未传参时对应属性值为None,直接调用字符串的
startswith()方法会触发属性异常 - 函数强耦合全局变量:两个核心业务函数没有设置入参,完全依赖全局sys.argv取值,无法适配动态传入的参数
重构优化方案
1. 彻底移除硬编码取值逻辑
所有需要外部传入的值(S3前缀index、查询开始时间、查询结束时间)全部通过函数入参传递,删除所有对sys.argv固定索引的读取代码
2. 修正时间匹配判断逻辑
替换错误的表达式,明确匹配规则:只要S3对象解析出的开始/结束时间字段,和用户输入的查询时间前缀任意匹配,即判定为命中结果;同时增加空值校验,避免None类型触发异常
3. 调整argparse参数配置
- 给核心参数设置必填校验,未传参时直接输出友好提示
- 移除冗余的sys.argv长度判断逻辑,完全由argparse处理参数合法性校验
- 修正原代码中类型注解的错误,补充缺失的boto3导入
4. 修正日志配置位置
将logging初始化逻辑移到程序启动阶段,避免在循环内重复触发配置导致的日志写入异常
重构后参考代码
import argparse import logging import time from boto3 import resource # 补充原脚本缺失的导入 FILE = 'bucket' TIME_FORMAT = "%m-%d-%Y-%H:%M:%S" def get_file(prefix: str): """根据传入的S3前缀拉取匹配的对象""" s3 = resource('s3') bucket = s3.Bucket(FILE) objects = bucket.objects.filter(Prefix=prefix) return objects def convert_epoch(input_epoch: str): """将epoch时间戳转换为人类可读格式""" converted_epoch_value = time.strftime(TIME_FORMAT, time.localtime(int(input_epoch))) return converted_epoch_value def convert_index(index: str, start_time: str, end_time: str): """遍历S3对象,匹配时间范围并输出结果""" dir_files = get_file(prefix=index) for file in dir_files: output = file.key if 'db_' not in output: continue output_dir = output.split('/') fields = output_dir[2].split('_') try: # 转换对象内的epoch时间字段 obj_start = convert_epoch(fields[1]) obj_end = convert_epoch(fields[2]) # 修正原判断逻辑:只要任意时间字段和查询输入匹配即命中 match_flag = ( obj_start.startswith(start_time) or obj_end.startswith(start_time) or obj_end.startswith(end_time) ) if match_flag: print(f"{output}\t\t is {obj_start}_{obj_end}") except ValueError as ve: logging.info(f"时间转换失败: {ve}") def main(): parser = argparse.ArgumentParser( description="Supply the directory you want to search files for. Give earliest and latest time to query bucket for" ) # 设置核心参数为必填,避免空值触发异常 parser.add_argument('-i', '--index', required=True, help='S3目录前缀,示例: format_files.py -i folder/folder') parser.add_argument('-s', '--start_time', required=True, help='查询起始时间前缀,示例: 09-17-2024') parser.add_argument('-e', '--end_time', required=True, help='查询结束时间前缀,示例: 09-18-2024') args = parser.parse_args() # 初始化日志配置(移到主流程,避免循环内重复配置) logging.basicConfig( level=logging.INFO, filename='logfile.log', format='%(asctime)s - %(levelname)s - %(message)s' ) convert_index( index=args.index, start_time=args.start_time, end_time=args.end_time ) if __name__ == "__main__": main()
重构后调用方式示例:
python format_files.py -i backup/db/ -s 09-01-2024 -e 09-10-2024
完全不需要依赖固定位置的参数索引,argparse会自动匹配带前缀的参数值,不会再出现取值错位的问题。
内容的提问来源于stack exchange,提问作者zendannyy
相关产品推荐
相关产品推荐

