Python 命令行参数基础:sys.argv 用法
文章目录
P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。
前言
兄弟们,先问个扎心的问题:你写Python代码多少年了?是不是天天在IDE里点运行按钮,把文件路径、模型参数、处理阈值全写死在代码里,结果一到要把脚本发给同事用,或者要放到服务器跑定时任务,别人一改参数就得改源码,当场社死?是不是见过大佬的Python脚本一行命令就能传各种配置,跑不同的业务逻辑,自己却连sys.argv是啥都搞不清,只会对着代码里的硬编码改来改去,改一次跑一次?
我在AI行业摸爬滚打了22年,见过太多写了3-5年Python的开发者,甚至包括不少天天写AI算法、自动化脚本的老哥,代码写得丝滑流畅,结果一到要做脚本化、工具化就抓瞎。明明一个sys.argv就能搞定的事,非要让用户去改源码里的路径和参数,最后不是用户改坏了代码跑不起来,就是线上环境因为硬编码的路径出了生产事故。
更离谱的是,很多新手一上来就为了处理两个参数,去装click、fire这些第三方库,甚至搞一套复杂的参数解析框架,结果脚本发给别人,人家一运行就报ModuleNotFoundError,连第一步都跑不起来。完全忘了Python原生就给我们提供了零依赖、全平台兼容、所有版本都能用的命令行参数解决方案——sys.argv。
这篇文章,我就用最通俗的段子和类比,从零到一带你吃透sys.argv,从基础用法到高频踩坑,再到2026年AI开发、自动化场景的实战案例,看完你就能写出不用改源码、一行命令就能跑的专业Python脚本。哪怕你是刚学Python的高中生,也能看懂、能上手。
一、先搞懂:sys.argv到底是个啥?为啥你一定要学?
1.1 先掰明白:什么是命令行参数?
很多新手一听到“命令行参数”就头大,觉得是什么高大上的底层技术,其实说白了,它就跟你点外卖时的备注要求一模一样。
你打开终端敲python xxx.py,这就相当于你打开外卖APP,选好了商家和主品(也就是你的Python脚本);而你在后面加的python xxx.py 123 abc /home/data,这些空格隔开的内容,就是你给脚本传的“备注要求”,也就是命令行参数。
平时你在IDE里写死参数,就像你每次点外卖,都要重新填一遍收货地址、口味、加不加料,每次改需求都要重新编辑整个订单;而用命令行参数,就像你把订单模板做好了,每次下单只需要改几个核心选项,完全不用动模板本身——也就是不用改你的Python源码。
可能有兄弟会说:我就在IDE里跑脚本,不用命令行,学这个有啥用?
我只能说,2026年了,AI时代都来了,你写的代码总不能永远只在自己电脑上跑吧?
- 你写了个AI图片批量推理脚本,要发给同事用,总不能让人家连Python都没搞懂,就去改你源码里的模型路径、输入文件夹吧?
- 你写了个数据处理脚本,要放到服务器上跑定时任务,总不能每次改个日期范围,都要登服务器改源码吧?
- 你写了个小工具,要开源给网友用,总不能让每个人都去改代码里的硬编码,最后全来给你提issue说跑不起来吧?
而sys.argv,就是解决这些问题的最优解——零依赖、全平台兼容、简单到极致,只要装了Python就能用,不用额外装任何库,走到哪都能跑。
1.2 sys.argv的本质:就是个普通Python列表,没什么神秘的
很多新手把sys.argv想的太复杂,其实它本质上就是Python给你内置好的一个普通列表(list),没有任何花里胡哨的黑魔法。你只要会用Python的列表,就会用sys.argv。
这个列表里的内容,规则简单到离谱:
- 列表的第一个元素(索引0),永远是你当前运行的脚本本身的名字(或者你敲的脚本路径)
- 列表里从第二个元素(索引1)开始,就是你在命令行里敲的、用空格分隔的所有参数
- 不管你敲的是数字、字母、路径,所有内容进了sys.argv,全都会变成字符串类型
我给你举个最简单的例子,你一眼就能懂。
我们新建一个Python文件,名字叫test.py,里面只写三行代码:
# 先导入sys模块,就像你进小区要先刷门禁卡
import sys
# 直接打印sys.argv这个列表
print("sys.argv的内容是:", sys.argv)
# 打印它的类型,给你看看是不是真的是列表
print("sys.argv的类型是:", type(sys.argv))
现在我们打开终端,运行这个脚本,看看会发生什么。
场景1:只运行脚本,不传任何参数
命令:python test.py
输出结果:
sys.argv的内容是: ['test.py']
sys.argv的类型是: <class 'list'>
你看,没有传任何参数的时候,sys.argv里只有一个元素,就是脚本名test.py。
场景2:运行脚本,传多个参数
命令:python test.py hello 123 3.14 /home/ai/data
输出结果:
sys.argv的内容是: ['test.py', 'hello', '123', '3.14', '/home/ai/data']
sys.argv的类型是: <class 'list'>
看到了吗?你在命令行里用空格隔开的每一段内容,都按顺序变成了sys.argv列表里的元素,哪怕你敲的是数字123、3.14,进了列表也全变成了字符串。
这里我给你打个比方,就像你去奶茶店点单,你对着店员喊:“奶茶 三分糖 加珍珠 少冰”。店员手里的订单本,第一行永远是你点的主品“奶茶”,后面的每一行,就是你提的要求,不管你说的是数字“三分糖”还是文字“加珍珠”,店员都会先统一记成文字,回头再给后厨转成对应的操作——就像你后面要把字符串转成int、float类型一样。
就这么简单,sys.argv没有任何神秘的地方,它就是个存了脚本名和命令行参数的列表,你会操作列表,就会用它。
二、从零到一:sys.argv的基础用法,看完就能上手
2.1 第一步:先搞对导入,别上来就踩坑
我见过太多新手,上来就直接写print(argv),然后运行就报NameError: name 'argv' is not defined,当场懵了,以为自己Python环境坏了。
其实原因特别简单:argv是sys模块里的属性,你必须先导入sys模块,才能用sys.argv,不能直接用argv。
这就像你想进小区拿快递,必须先刷门禁卡(import sys),不然你连小区门都进不去,更别说拿快递(用argv)了。很多新手上来就直接对着小区里喊“快递给我”,保安直接给你拦下来了,可不就报错了嘛。
正确的写法,永远是先在脚本最顶部导入sys:
import sys
# 后面才能用sys.argv
2.2 第二步:正确取值,索引别搞反了
前面我们说了,sys.argv[0]永远是脚本名,你真正要拿的用户参数,是从sys.argv[1] 开始的!这个点,80%的新手第一次用都会搞反。
我给你举个最常见的例子:写一个脚本,接收两个数字,输出它们的和。
新手常写的错误代码:
import sys
# 错误1:取了索引0,拿到的是脚本名,不是参数
a = sys.argv[0]
b = sys.argv[1]
# 错误2:没有转类型,直接相加,变成了字符串拼接
print(a + b)
你运行python sum.py 1 2,猜猜输出什么?结果是sum.py1,当场傻眼。为啥?因为你取了sys.argv[0]的脚本名,而且两个字符串相加,就是拼接在一起,根本不是数字求和。
正确的写法,要避开这两个核心坑:
import sys
# 先判断有没有传够参数,避免索引越界,新手必加
if len(sys.argv) < 3:
print("用法:python sum.py 数字1 数字2")
print("示例:python sum.py 1 2")
# 参数不对,直接优雅退出,不往下执行
sys.exit()
# 正确取值:从索引1开始,并且转成数字类型
a = float(sys.argv[1])
b = float(sys.argv[2])
# 计算并输出结果
print(f"两个数的和是:{a + b}")
我们运行这个脚本,看看效果:
- 正确传参:
python sum.py 10 20,输出两个数的和是:30.0 - 没传够参数:
python sum.py 10,会输出用法提示,不会直接报错崩溃 - 传了非数字:
python sum.py abc 20,会报类型错误,这个我们后面会讲怎么处理
这个正确的例子里,有三个你必须记住的核心要点,少一个都容易出问题:
- 索引从1开始取参数,0永远是脚本名,别搞错
- 必须先判断参数个数,不然用户没传够参数,直接取sys.argv[1]会报
IndexError: list index out of range,脚本直接崩了 - 必须做类型转换,sys.argv里的所有元素都是字符串,要做数字计算,必须转成int或者float,不然就是字符串拼接
2.3 基础场景实战:3个日常工作最常用的例子,拿来就能用
光说不练假把式,我给你整理了3个2026年程序员、AI开发者日常工作里最常用的场景,全是sys.argv就能搞定的,代码拿来就能改、就能用。
场景1:批量修改文件后缀名脚本
做AI数据处理、文件管理的兄弟,肯定经常遇到这种需求:把一个文件夹里的所有.jpg改成.jpeg,或者把.txt改成.csv,总不能一个个手动改吧?用这个脚本,一行命令搞定,不用改源码。
import sys
import os
# 先判断参数个数
if len(sys.argv) < 4:
print("用法:python rename.py 目标目录 原后缀 新后缀")
print("示例:python rename.py /home/ai/data jpg jpeg")
sys.exit()
# 从命令行获取参数
target_dir = sys.argv[1]
old_suffix = sys.argv[2].lstrip(".") # 去掉用户可能加的.
new_suffix = sys.argv[3].lstrip(".")
# 判断目录是否存在
if not os.path.isdir(target_dir):
print(f"错误:目录 {target_dir} 不存在")
sys.exit(1)
# 遍历目录里的所有文件
count = 0
for filename in os.listdir(target_dir):
# 匹配原后缀的文件
if filename.endswith(f".{old_suffix}"):
# 拼接完整路径
old_path = os.path.join(target_dir, filename)
# 生成新文件名
new_filename = filename.replace(f".{old_suffix}", f".{new_suffix}")
new_path = os.path.join(target_dir, new_filename)
# 重命名
os.rename(old_path, new_path)
count += 1
print(f"已修改:{filename} -> {new_filename}")
print(f"操作完成,共修改了 {count} 个文件")
运行方式:python rename.py ./data jpg png,就能把data文件夹里所有的.jpg文件改成.png,不用改一行代码,换目录、换后缀直接改命令行参数就行。
场景2:AI批量推理脚本
2026年了,大家都玩大模型、图像识别、AI绘图,写个推理脚本,总不能每次换个模型、换个输入文件夹都改代码吧?用sys.argv传参数,一行命令搞定,发给同事直接就能用。
import sys
import os
import cv2
import numpy as np
# 这里用onnxruntime做推理,主流AI推理框架
import onnxruntime as ort
if len(sys.argv) < 4:
print("用法:python infer.py 模型路径 输入图片文件夹 输出结果文件夹")
print("示例:python infer.py ./models/face_recog.onnx ./input_imgs ./output_result")
sys.exit()
# 从命令行获取参数
model_path = sys.argv[1]
input_dir = sys.argv[2]
output_dir = sys.argv[3]
# 校验模型文件
if not os.path.exists(model_path):
print(f"错误:模型文件 {model_path} 不存在")
sys.exit(1)
# 校验输入目录
if not os.path.isdir(input_dir):
print(f"错误:输入目录 {input_dir} 不存在")
sys.exit(1)
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 加载模型
session = ort.InferenceSession(model_path)
input_name = session.get_inputs()[0].name
input_shape = session.get_inputs()[0].shape
print(f"模型加载成功,输入要求:{input_shape}")
# 批量处理图片
img_suffix = ["jpg", "jpeg", "png", "bmp"]
count = 0
for filename in os.listdir(input_dir):
# 过滤图片文件
if filename.split(".")[-1].lower() not in img_suffix:
continue
# 读取图片
img_path = os.path.join(input_dir, filename)
img = cv2.imread(img_path)
if img is None:
print(f"警告:无法读取图片 {filename},已跳过")
continue
# 预处理:resize到模型要求的尺寸,归一化
h, w = input_shape[2], input_shape[3]
img_resize = cv2.resize(img, (w, h))
img_input = img_resize.transpose(2, 0, 1)[np.newaxis, :, :, :].astype(np.float32) / 255.0
# 推理
result = session.run(None, {input_name: img_input})
# 保存结果
output_path = os.path.join(output_dir, f"{filename.split('.')[0]}_result.npy")
np.save(output_path, result)
count += 1
print(f"已处理:{filename},结果已保存")
print(f"推理完成,共处理了 {count} 张图片")
这个脚本,你发给同事,同事不用改你一行代码,只要把自己的模型路径、输入输出文件夹传进去就能跑,这不比你让同事改源码里的路径香?还不会出现同事改坏代码的情况。
场景3:定时任务日志脚本
服务器上跑定时任务,最常用的就是日志脚本,用sys.argv传日志级别和保存路径,不用每次改定时任务的代码,直接改命令行参数就行。
import sys
import os
from datetime import datetime
if len(sys.argv) < 3:
print("用法:python task_log.py 日志级别 日志保存路径")
print("示例:python task_log.py info /var/log/ai_daily_task.log")
sys.exit()
# 从命令行获取参数
log_level = sys.argv[1].lower()
log_path = sys.argv[2]
# 日志级别映射
level_map = {
"debug": 0,
"info": 1,
"warn": 2,
"error": 3
}
if log_level not in level_map:
print(f"错误:不支持的日志级别 {log_level},支持的级别:debug/info/warn/error")
sys.exit(1)
# 创建日志目录
log_dir = os.path.dirname(log_path)
if log_dir and not os.path.exists(log_dir):
os.makedirs(log_dir)
# 写日志的函数
def write_log(level, content):
if level_map[level] >= level_map[log_level]:
time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_line = f"[{time_str}] [{level.upper()}] {content}\n"
# 追加写入日志文件
with open(log_path, "a", encoding="utf-8") as f:
f.write(log_line)
# 同时打印到控制台
print(log_line, end="")
# 这里写你的定时任务逻辑
write_log("info", "每日AI数据同步任务开始执行")
try:
# 模拟任务执行
write_log("debug", "正在连接数据库")
write_log("debug", "正在拉取今日新增数据")
write_log("info", "今日共拉取1256条新数据")
write_log("debug", "正在清洗数据")
write_log("debug", "正在写入AI训练库")
write_log("info", "任务执行成功")
except Exception as e:
write_log("error", f"任务执行失败:{str(e)}")
sys.exit(1)
运行方式:python task_log.py debug ./task.log,就能输出debug级别的所有日志;如果是线上正式跑,就用python task_log.py info ./task.log,只输出info及以上级别的日志,不用改一行代码,直接在定时任务里改命令行参数就行。
三、90%的人都会踩的sys.argv坑,我帮你全踩过了,别再掉进去
我搞了22年开发,见过太多人,哪怕是工作了好几年的老手,都栽在这些sys.argv的基础坑里,轻则脚本跑不起来,重则线上出生产事故。今天我把这些坑全给你列出来,讲清楚怎么踩的、怎么避免,看完你就能少走90%的弯路。
3.1 天坑一号:忘了参数全是字符串,不做类型转换
这个是90%的新手第一次用都会踩的坑,没有之一。
前面我们反复强调,sys.argv里的所有元素,不管你敲的是数字还是字母,全都是字符串类型。很多新手忘了这一点,直接拿参数做数字运算、大小比较,结果要么直接报错,要么出现离谱的结果。
踩坑示例1:直接做数字比较,报错
import sys
age = sys.argv[1]
# 直接拿字符串和数字比较,直接报TypeError
if age > 18:
print("成年了")
else:
print("未成年")
运行python age.py 20,直接报错:TypeError: '>' not supported between instances of 'str' and 'int',当场懵了。
踩坑示例2:隐蔽的字符串比较,结果完全错误
这个坑更离谱,很多老手都偶尔会踩。比如你写个脚本比较两个数字的大小:
import sys
a = sys.argv[1]
b = sys.argv[2]
if a > b:
print(f"{a} 比 {b} 大")
else:
print(f"{a} 比 {b} 小")
你运行python compare.py 100 20,猜猜输出什么?结果是100 比 20 小!
是不是离谱到家了?为啥?因为字符串的比较,是按每个字符的ASCII码来比的,"100"的第一个字符是’1’,ASCII码是49;“20"的第一个字符是’2’,ASCII码是50。49 < 50,所以字符串"100” < “20”,结果就完全错了。
避坑方案:
只要是数字类型的参数,必须先转成int或者float,再做运算和比较。就像你去超市买东西,店员扫条码,必须把条码的字符串转成商品的价格数字,才能算总价,不能直接拿条码字符串去算钱。
正确写法:
import sys
if len(sys.argv) < 3:
print("用法:python compare.py 数字1 数字2")
sys.exit()
# 先转成数字类型
a = float(sys.argv[1])
b = float(sys.argv[2])
if a > b:
print(f"{a} 比 {b} 大")
else:
print(f"{a} 比 {b} 小")
3.2 天坑二号:不判断参数个数,直接索引取值,导致索引越界
新手最常写的代码,就是上来直接a = sys.argv[1],完全不判断用户有没有传这个参数。结果用户运行的时候,少传了一个参数,直接报IndexError: list index out of range,脚本直接崩了。
尤其是线上跑定时任务的时候,参数少传了一个,任务直接崩了,你查日志都要查半天,才发现是这么个低级错误。
踩坑示例:
import sys
# 直接取值,不判断有没有参数
input_path = sys.argv[1]
output_path = sys.argv[2]
print(f"从{input_path}读取数据,保存到{output_path}")
用户运行python task.py ./input,只传了一个参数,直接报错索引越界,脚本崩溃。
避坑方案:
必须先判断len(sys.argv)的长度,够不够你需要的参数个数。不够的话,给用户提示正确的用法,然后用sys.exit()优雅退出,绝对不能直接取值。
就像你去餐厅吃饭,服务员先看你点的菜够不够下锅,你只点了个火锅底料,没点菜,服务员肯定会提醒你,而不是直接给你上一锅开水。
3.3 天坑三号:参数里有空格,没加引号,导致参数被拆分
这个坑,很多老手都偶尔会踩,尤其是Windows用户,路径里经常有空格,比如C:\Users\AI 教程\data,结果一运行就报错路径不存在,找半天找不到原因。
踩坑示例:
你写了个脚本,接收一个路径参数:
import sys
import os
if len(sys.argv) < 2:
print("用法:python check_path.py 路径")
sys.exit()
path = sys.argv[1]
print(f"你输入的路径是:{path}")
print(f"路径是否存在:{os.path.exists(path)}")
你运行python check_path.py C:\Users\AI 教程\data,结果输出:
你输入的路径是:C:\Users\AI
路径是否存在:False
为啥?因为sys.argv是按空格拆分参数的,你带空格的路径,被拆成了两个参数,sys.argv[1]是C:\Users\AI,sys.argv[2]是教程\data,路径自然就不对了。
避坑方案:
带空格的参数,必须用双引号(Windows)或者单引号(Linux/Mac)包起来。
正确的运行命令:python check_path.py "C:\Users\AI 教程\data",这样sys.argv就会把整个引号里的内容当成一个元素,不会拆分,路径就正确了。
就像你点外卖,备注里有一句话“多放辣,不要香菜,谢谢”,你必须把这句话写在同一个备注框里,不能拆成好几条,不然商家就会当成好几个要求,给你做错。
3.4 天坑四号:以为sys.argv[0]是绝对路径,结果获取脚本路径出错
很多新手以为sys.argv[0]是脚本的绝对路径,其实根本不是。sys.argv[0]的值,完全取决于你运行脚本的时候,敲的是什么路径。
比如你的脚本在/home/ai/script.py:
- 你在
/home/ai/目录下,运行python script.py,sys.argv[0]就是script.py(只有文件名,没有路径) - 你运行
python /home/ai/script.py,sys.argv[0]就是/home/ai/script.py(完整绝对路径) - 你在
/home/目录下,运行python ai/script.py,sys.argv[0]就是ai/script.py(相对路径)
很多新手用sys.argv[0]去拼接脚本所在目录的其他文件,结果换个目录运行脚本,就报错找不到文件。
避坑方案:
如果你要获取脚本的绝对路径,或者脚本所在的目录,必须用os.path模块做处理,不能直接用sys.argv[0]。
正确写法:
import sys
import os
# 获取脚本的绝对路径
script_abs_path = os.path.abspath(sys.argv[0])
# 获取脚本所在的目录
script_dir = os.path.dirname(script_abs_path)
print(f"脚本绝对路径:{script_abs_path}")
print(f"脚本所在目录:{script_dir}")
这样不管你在哪个目录运行脚本,都能正确获取到脚本的绝对路径和所在目录,不会出错。
四、sys.argv的进阶用法:不止是传参数,这些技巧能让你的脚本更专业
4.1 处理不定数量的参数:传多少接多少,不用固定个数
很多时候,我们不知道用户会传多少个参数,比如要写个脚本,计算任意多个数字的和,不管用户传1个还是100个数字,都能算。这时候就可以用列表切片sys.argv[1:],把除了脚本名之外的所有参数都拿出来,灵活处理。
完整示例:任意多个数字求和脚本
import sys
# 拿到所有用户传入的参数,排除脚本名
args = sys.argv[1:]
# 判断有没有传参数
if not args:
print("用法:python sum_all.py 数字1 数字2 数字3 ...")
print("示例:python sum_all.py 1 2 3 4 5")
sys.exit(1)
# 遍历参数,转成数字求和,加异常处理
total = 0
valid_count = 0
for arg in args:
try:
# 尝试转成浮点数
num = float(arg)
total += num
valid_count += 1
except ValueError:
# 转失败了,给出警告,跳过
print(f"警告:【{arg}】不是有效的数字,已跳过")
# 输出结果
print(f"有效数字个数:{valid_count}")
print(f"所有有效数字的和是:{total}")
这个脚本,你传多少个数字都能算,比如:
- 运行
python sum_all.py 1 2 3 4 5,输出和为15 - 运行
python sum_all.py 10 20 abc 30,会警告abc不是有效数字,输出和为60 - 哪怕你传100个数字,也能正常计算,不用改一行代码
就像你去奶茶店,不管你加多少种小料,店员都能给你算总价,不会因为你加的多就不会算了。
4.2 配合sys.exit(),用退出码告诉上级脚本执行结果
前面我们多次用到了sys.exit(),很多新手只知道它能退出脚本,却不知道它还能传退出码,这个功能在Linux定时任务、shell脚本、自动化流程里特别有用。
sys.exit()的规则:
sys.exit(0):代表脚本正常执行成功退出sys.exit(非0数字):代表脚本异常退出,不同的数字可以代表不同的错误类型
比如,我们可以规定:
- 退出码1:参数个数不对
- 退出码2:输入路径不存在
- 退出码3:模型文件加载失败
这样,你的上级shell脚本,就能根据退出码,判断你的Python脚本有没有跑成功,失败的原因是什么,从而做对应的处理,比如失败了发告警、重试等。
示例:带规范退出码的脚本
import sys
import os
if len(sys.argv) < 3:
print("用法:python process.py 输入目录 模型文件")
# 参数错误,退出码1
sys.exit(1)
input_dir = sys.argv[1]
model_path = sys.argv[2]
if not os.path.isdir(input_dir):
print(f"错误:输入目录 {input_dir} 不存在")
# 路径不存在,退出码2
sys.exit(2)
if not os.path.exists(model_path):
print(f"错误:模型文件 {model_path} 不存在")
# 模型不存在,退出码3
sys.exit(3)
# 这里写业务逻辑
print("所有校验通过,开始执行任务...")
# 任务执行成功
print("任务执行完成")
sys.exit(0)
4.3 什么时候用sys.argv?什么时候用argparse?
很多新手会问:Python还有个argparse标准库,也是处理命令行参数的,还有第三方的click、fire,我该用哪个?
这里我给你讲的明明白白,不用纠结:
| 特性 | sys.argv | argparse | 第三方库(click/fire) |
|---|---|---|---|
| 依赖 | 零依赖,原生自带 | 零依赖,原生自带 | 需要安装第三方库 |
| 复杂度 | 极简,5分钟学会 | 中等,需要学习参数配置 | 有学习成本,需要看文档 |
| 帮助文档 | 需要自己写 | 自动生成–help帮助文档 | 自动生成帮助文档 |
| 适用场景 | 简单参数、小脚本、快速原型 | 多参数、带选项、正式工具 | 复杂命令行工具、开源项目 |
说白了,sys.argv就像你家门口的便利店,买瓶水、买包烟,快速方便,不用走流程;argparse就像大超市,东西全,品类多,适合买很多东西,但是要走入口、结账,流程多一点;第三方库就像大型商场,啥都有,但是你得专门开车过去,还要找停车位。
2026年了,很多新手上来就装一堆第三方库,处理个简单的两个参数,非要用click、fire,其实完全没必要。sys.argv就能搞定的事,零依赖,脚本发给别人,直接就能跑,不用让用户先装一堆库,这不香吗?
只有当你的脚本参数很多,有很多可选选项,需要给用户提供完善的帮助文档,做正式的工具的时候,再用argparse或者第三方库。
五、2026年实战案例:用sys.argv写一个AI训练数据预处理脚本,拿来就能用
最后,我给你一个完整的、2026年AI开发里天天都能用到的实战脚本——AI图像训练数据批量预处理脚本。做计算机视觉的兄弟都知道,训练模型前,必须把所有图片统一resize、归一化、格式转换,这个脚本用sys.argv传所有参数,不用改一行代码,一行命令就能跑。
import sys
import os
import cv2
import numpy as np
from tqdm import tqdm
def main():
# 校验参数个数
if len(sys.argv) < 6:
print("="*50)
print("AI训练数据批量预处理脚本")
print("用法:python preprocess.py 输入目录 输出目录 目标宽度 目标高度 图片格式")
print("示例:python preprocess.py ./raw_imgs ./train_imgs 640 640 jpg")
print("参数说明:")
print(" 输入目录:原始图片所在的文件夹")
print(" 输出目录:预处理后图片保存的文件夹")
print(" 目标宽度:resize后的图片宽度")
print(" 目标高度:resize后的图片高度")
print(" 图片格式:输出的图片格式,支持jpg/png/bmp")
print("="*50)
sys.exit(1)
# 从命令行获取所有参数
input_dir = sys.argv[1]
output_dir = sys.argv[2]
try:
target_w = int(sys.argv[3])
target_h = int(sys.argv[4])
except ValueError:
print("错误:目标宽度和高度必须是整数")
sys.exit(1)
output_format = sys.argv[5].lower()
# 校验参数合法性
if target_w <= 0 or target_h <= 0:
print("错误:目标宽度和高度必须大于0")
sys.exit(1)
if output_format not in ["jpg", "png", "bmp"]:
print(f"错误:不支持的输出格式 {output_format},支持的格式:jpg/png/bmp")
sys.exit(1)
if not os.path.isdir(input_dir):
print(f"错误:输入目录 {input_dir} 不存在")
sys.exit(1)
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
print(f"提示:已创建输出目录 {output_dir}")
# 支持的图片后缀
support_suffix = ["jpg", "jpeg", "png", "bmp", "tiff"]
# 遍历输入目录,获取所有图片
img_list = []
for filename in os.listdir(input_dir):
suffix = filename.split(".")[-1].lower()
if suffix in support_suffix:
img_list.append(filename)
if not img_list:
print(f"警告:输入目录 {input_dir} 里没有找到支持的图片")
sys.exit(0)
print(f"找到 {len(img_list)} 张图片,开始预处理...")
print(f"目标尺寸:{target_w}x{target_h},输出格式:{output_format}")
# 批量处理图片,带进度条
success_count = 0
fail_count = 0
for filename in tqdm(img_list, desc="预处理进度"):
try:
# 读取图片
img_path = os.path.join(input_dir, filename)
img = cv2.imread(img_path, cv2.IMREAD_COLOR)
if img is None:
print(f"警告:无法读取图片 {filename},已跳过")
fail_count += 1
continue
# 等比例resize,保持宽高比,填充黑边
h, w = img.shape[:2]
# 计算缩放比例
scale = min(target_w / w, target_h / h)
new_w = int(w * scale)
new_h = int(h * scale)
# 缩放图片
img_resize = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_AREA)
# 创建目标尺寸的黑底画布
canvas = np.zeros((target_h, target_w, 3), dtype=np.uint8)
# 把缩放后的图片放到画布中间
x_offset = (target_w - new_w) // 2
y_offset = (target_h - new_h) // 2
canvas[y_offset:y_offset+new_h, x_offset:x_offset+new_w, :] = img_resize
# 生成输出文件名
output_filename = f"{filename.split('.')[0]}.{output_format}"
output_path = os.path.join(output_dir, output_filename)
# 保存图片
if output_format == "jpg":
cv2.imwrite(output_path, canvas, [cv2.IMWRITE_JPEG_QUALITY, 95])
else:
cv2.imwrite(output_path, canvas)
success_count += 1
except Exception as e:
print(f"错误:处理图片 {filename} 失败,原因:{str(e)}")
fail_count += 1
# 输出处理结果
print("="*50)
print("预处理完成!")
print(f"成功处理:{success_count} 张")
print(f"处理失败:{fail_count} 张")
print(f"处理后的图片已保存到:{output_dir}")
print("="*50)
if __name__ == "__main__":
main()
这个脚本,是我平时做AI项目天天用的,功能非常完善:
- 等比例resize,保持图片宽高比,不会拉伸变形,填充黑边
- 支持多种输入图片格式,输出格式可指定
- 带进度条,能看到处理进度
- 完善的异常处理,单张图片处理失败不会影响整个脚本
- 所有参数全从命令行传入,不用改一行代码
运行方式也特别简单,比如:python preprocess.py ./raw_data ./train_data 640 640 jpg
就能把raw_data里的所有图片,统一处理成640x640的jpg图片,保存到train_data里。
你可以根据自己的需求,修改里面的预处理逻辑,比如改成批量灰度化、批量归一化、批量加水印,都可以,参数还是用sys.argv传,非常灵活。
P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。
更多推荐

所有评论(0)