文章目录
- 0. 引言
- 1. argparse简介
- 2. argparse的使用
- 3. 实例操作
- 4. 代码运行
- 4.1 命令行执行
- 4.1 IDE执行
- 5. 总结
0. 引言
在深度学习的过程中,我们常常需要操作和调参大量的参数。如果采用硬编码(直接在代码中赋值)的方式来设置这些参数,不仅会让修改参数变得极其繁琐,还容易引入错误。在深度学习的代码实践中,更常见且高效的做法是使用 argparse
这一库来进行参数管理。这种方法不仅整洁,而且便于参数的调整与管理。然而,我个人总感觉对这部分内容的理解尚不够深刻,因此,我决定仔细研究 argparse
,希望我的探索能为大家带来一些帮助。
重点强调下本文参考学习的链接,感兴趣有能力的童鞋可以先阅读下原文
1. argparse简介
argsparse是python的命令行解析的标准模块,内置于python,不需要安装。这个库可以让我们直接在命令行中就可以向程序中传入参数并让程序运行。
上面这句话是什么意思呢。python的命令行解析标准模块???
·
我对着话解读一下:
·
其实就是在例如mac中的终端和win中的cmd下,这样的一个纯命令行环境下。我们称这样的环境为命令行,但是现阶段大多数用的还是ide这样的可视化环境取运行。假如你在使用命令行界面执行代码的时候实际上都是不考虑代码本身,而是直接开始进行接口接上直接运行的。举个例子你看电视会考虑电视是如何相识图像的吗??不会吧,仅仅使用± 进行调台吧。因此±就是你赋予命令行的参数,你在和程序进行交互。而这就是这个argsparse的能力,命令行就是这个遥控器,你得输入的参数就是指令而python文件就是电视。argsparse这个模块赋予了命令行界面这样的能力,这最大的好处就是代码对程序的执行者而言就是黑盒子,所以只需要考虑代码是如何运行的或者是更好的运行,不用考虑更多,将修改参数的操作和代码隔离开也是更好的保护代码,其修改参数的难度也会降低。
·虽然大多数初学者很少用终端这样的纯代码架构:许多开发者可能倾向于在集成开发环境(IDE)中使用图形化界面进行编程和调试,这可能会让人感觉命令行和
argparse
的重要性有所下降。然而,argparse
在很多场景下仍然是极其有用和重要的工具。这并不仅限于直接通过命令行执行程序时的参数传递和处理。以下是argparse
仍然非常关键的几个方面:
模块与代码封装:
argparse
可以被看作是一种封装机制,它允许开发者将应用程序的配置抽象出来,从而使程序在不同环境或条件下运行时更加灵活。自动化与脚本执行:在自动化脚本和批处理任务中,
argparse
提供了一种向脚本传递参数和修改其行为的高效方式。这在自动化测试、数据处理和系统管理中尤其有用。复杂项目和多环境部署:对于需要在多种环境(开发、测试、生产等)中运行,或者参数经常变化的复杂项目,通过命令行参数来控制程序行为是一种常见的做法。
argparse
使这个过程更加标准化和简化。深度学习和数据科学领域:在这些领域,实验通常需要根据不同的数据集或不同的模型配置多次运行相同的代码。使用
argparse
来管理这些参数可以极大提高实验的效率,并方便结果的复现。因此,即使在图形化界面的使用日益普及的今天,
argparse
仍然是一个强大的工具,尤其是对于那些需要高度灵活性和可配置性的应用程序来说。它提供了一种有效的方式来处理程序外部参数,使得代码更加模块化,易于维护和扩展。
2. argparse的使用
使用 argparse
模块构建命令行界面程序主要包括以下四个简单步骤:
-
导入
argparse
包:
首先,你需要通过import argparse
语句来导入argparse
包,这使得你能够访问该模块提供的功能。 -
创建命令行解析器对象:
接下来,通过实例化ArgumentParser
对象来创建一个命令行解析器。你可以在实例化时提供一个描述字符串作为参数,这个描述将在命令行(简单理解就是你在终端运行python文件会看到。)中使用-h/--help
查看帮助信息时显示。这个解析器对象是你命令行界面的核心,负责处理传入的命令行参数。 -
给解析器添加命令行参数:
然后,通过调用创建的解析器对象上的add_argument()
方法来添加需要的命令行参数。这一步很关键,因为它定义了用户可以向你的程序传递哪些参数,这包括参数的名字、类型、默认值等。通过精心设计这些参数,你可以使你的命令行程序变得既强大又易于使用。其强大的点就是其不再是简单的赋值,会分析用户传入的信息 -
解析命令行的参数:
最后,通过调用解析器对象的parse_args()
方法来分析命令行提供的参数(即用户添加进来的参数,和其他冲突对数值进行选择)。这一步会根据你之前定义的参数规则来解析用户输入的参数,并将分析结果保存在一个命名空间对象中。这也作文最终会使用的参数,这个对象将作为解析结果,提供展示给你的程序使用。
3. 实例操作
下面是按上述步骤实践的实例代码:
import argparse # 1 导入 `argparse` 包
parser = argparse.ArgumentParser(description='命令行中传入一个数字') # 创建命令行解析器对象
# description就是这个用于集成各种参数的实例描述
# 上述过程已经完成了使用教程中的第1,2步操作了。下面为3,4步的操作流程
实质上3,4操作就是parser对象的两种常用方法
首先来看第3步需要使用的方法parser.add_argument
parser.add_argument
是argparse
模块中ArgumentParser
对象的一个方法,用于向你的程序添加命令行参数规则。这个方法非常灵活,提供了多种选项来定义参数的行为和如何处理传入的数据。下面我将解释
add_argument
方法中一些常用的参数及其用法:name or flags
- 这是
add_argument
方法中的第一个位置参数,表示参数的名称或标志。位置参数是没有前缀的(如integers
),而可选参数通常使用前缀-
或--
(如-i
或
--integers
)。位置参数在命令行中是必须的,而可选参数不是。type
type
参数定义了命令行参数应该被转换成的类型。常用的类型包括int
、float
和str
等。如果不指定,默认为字符串类型。help
help
参数提供了一个描述,说明这个参数做什么用。这个描述会在程序的帮助文本中显示,通常可以通过命令行运行程序时加上-h
或--help
参数查看。default
default
参数指定了参数的默认值。如果命令行中没有提供这个参数,则使用该默认值。required
- 对于可选参数(即使用
--
前缀定义的),required=True
指定这个参数虽然是以可选参数的形式定义的,但是在命令行中是必须提供的。此选项只对可选参数有效。choices
choices
参数限制参数值必须从你提供的选项中选择。例如,choices=[1, 2, 3]
表示参数值必须是 1、2 或 3。action
action
参数定义了当参数在命令行中存在时应该进行的动作。一些常用的动作包括:
'store'
:存储参数的值(这是默认动作)。'store_true'
/'store_false'
:这些动作分别用于实现布尔开关,参数存在时将对应的变量设为True
或False
。'append'
:这个动作将参数出现的每个值添加到一个列表中。这允许同一个参数在命令行中出现多次,并收集所有的值。nargs
nargs
参数指定命令行参数应该消耗的数量。它可以是一个具体的数字,或者一些特殊字符,比如?
表示参数是可选的,*
表示参数可以出现任意次,+
表示参数至少要提供一次。这些是
add_argument
方法中的一些常用参数。根据你的需求合理使用这些参数,可以构建出非常灵活和强大的命令行界面。
可以看到有用的就那么几个,这里着重讲一下这个命名位置该如何设定:
即命名的方式会将参数变成两种类型的参数。
位置参数(Positional Arguments)和可选参数(Optional Arguments)
位置参数和可选参数
在 argparse
中,位置参数(Positional Arguments)和可选参数(Optional Arguments)的主要差异在于它们是否是命令行调用中必需的。
-
位置参数:是调用命令行程序时必须提供的参数。这意味着,在命令行中运行程序时,用户必须为每个定义的位置参数提供相应的值,且顺序也需要和定义时保持一致。如果缺少位置参数,程序会报错并显示帮助信息。
-
可选参数:如其名所示,这些参数在命令行中是可选的。它们通常由一个或两个短划线(
-
或--
)开头,后面跟参数名称。可选参数可以有默认值,也可以进行设置使其成为“必需的”(required=True
),但即便是设置为必需,它们也仍然保持可选参数的形式(即通过--option
的方式提供)。
和命令行互动进行赋值
所有参数(位置参数和可选参数)都能在命令行输入时激活并赋值。区别在于:
-
位置参数的值是基于它们在命令行中出现的位置来匹配的。
举个例子: -
可选参数则是根据参数名来识别和赋值的。
举个例子:
假设一个程序定义了一个位置参数 filename
和一个可选参数 --verbose
。
- 在命令行中调用这个程序时,必须提供
filename
参数的值;否则程序会报错并提示需要这个参数。
对于位置参数,其值的匹配确实是基于它们在命令行中出现的位置。这意味着,命令行中参数的顺序非常重要,因为它决定了哪个参数值会被解析并赋予到程序定义的哪个位置参数上。
让我们通过一个简单的示例来说明这一点:
示例脚本example.py
:import argparse # 创建解析器 parser = argparse.ArgumentParser(description="示例:位置参数的使用。") # 定义两个位置参数 parser.add_argument('first', type=int, help="第一个整数") parser.add_argument('second', type=str, help="第二个字符串") # 解析命令行参数 args = parser.parse_args() # 输出参数值 print(f"第一个参数(整数): {args.first}") print(f"第二个参数(字符串): {args.second}") ``` 在这个示例中,我们定义了两个位置参数:`first` 和 `second`,分别期待一个整数和一个字符串。 ### 运行脚本: 如果我们在命令行中运行这个脚本并按照顺序提供两个参数,比如: ```python example.py 123 hello ``` 那么,解析器会将 `123` 赋值给 `first` 参数,将 `"hello"` 赋值给 `second` 参数,因为这是它们在命令行中出现的顺序。因此,脚本的输出将是: ```第一个参数(整数): 123 第二个参数(字符串): hello ``` 这个简单的例子展示了位置参数如何基于命令行中的位置来进行匹配和赋值。因此,当使用位置参数时,提供给命令行程序的参数顺序至关重要,因为它直接决定了参数值如何被解析和使用。
--verbose
参数则可以根据需要提供或省略,如果省略,程序可以使用定义的默认行为。
在使用
argparse
模块时,通常是将默认值(default
参数)与可选参数结合使用。这是因为,对于位置参数,当用户不提供值时,程序会因为缺少必要的参数而报错,而不是使用默认值。因此,位置参数的主要用途是用于那些程序运行时必须由用户提供的值。要为一个可选参数设置默认值,可以使用
default
关键字参数:parser.add_argument('--myoption', default=10,help='一个可选参数,带有默认值')
在这个例子中,如果用户没有在命令行中指定
--myoption
,那么args.myoption
的值将会是
10
。这个做法对于那些不是必须由用户指定,但程序又需要一个预设值来正常运行的参数特别有用。总的来说,虽然可以对任何类型的参数设置默认值,但在实际应用中,为可选参数设置默认值是更常见且推荐的做法。
因此,赋予位置参数数值是根据位置来识别,而可选参数则是通过参数名来识别。希望这个解释能够帮助您更准确地理解和表述位置参数和可选参数的区别及其在命令行中的应用方式。
比较像类中赋值的* 后面的要指定方式的赋值。看不懂这句话的小伙伴可以跳过不影响阅读。
# 在命令行界面便于看到的使用者知道如何传入参数,以及这类参数来一个统一的描述,
#type是要传入的参数的数据类型 help中指导这个参数是咋个意思
parser.add_argument('integers', type=str, help='传入的数字')
第四步开始:
parser.parse_args()
是 argparse
模块中 ArgumentParser
对象的一个方法,它负责解析命令行输入的参数。这个方法读取 sys.argv
(命令行输入的字符串列表,包括脚本的名称和后续传递给脚本的参数),然后根据之前通过 add_argument()
方法定义的规则来解析这些参数。最终,parse_args()
返回一个包含所有命令行参数(已转换为适当类型)的 Namespace 对象。如果用户输入的参数不符合规则,argparse
会自动生成错误信息并停止脚本执行。
用更简单直白的话来说,
parser.parse_args()
方法的作用就是:它会读取并分析命令行中提供的参数,根据之前设定的规则(即我们通过add_argument()
方法设定的规则)来判断哪些参数是有效的,哪些参数的格式正确,并将这些参数及其值以一种容易使用的方式存储起来(通常是一个名为args
的对象)。
这也是为啥被官方文件称为解析的原因。
换句话说,parse_args()
让我们能够在命令行中输入各种参数,并且程序会根据我们之前定义好的规则来“理解”这些参数。一旦参数被“理解”和确认无误,它们就会被存储在一个特定的对象中,我们可以在程序的其他部分直接访问这些参数值,而不用担心参数解析的细节问题。这让命令行程序的开发变得既简单又直观。
args = parser.parse_args()
#获得传入的参数
print(args) # 输出解析出的参数,告诉使用者最终的参数选择情况,让这一行为可视化
4. 代码运行
本节特别强调 argparse
的使用和运行,主要是因为在命令行界面(CLI)与集成开发环境(IDE)如 PyCharm 和 VSCode 中,argparse
的使用方式存在明显差异,这种差异可能会导致一些意料之外的问题。虽然大多数深度学习代码因其操作的便捷性而倾向于在命令行中执行,但许多初学者更习惯于使用 IDE 进行代码开发和调试。因此,为了帮助大家理解这些可能遇到的问题并有效地使用 argparse
,本节将通过两种方法详细解释这些复杂的行为。
4.1 命令行执行
首先明确接下来操作的步骤和所使用的代码示例:
import argparse
# 创建命令行参数解析器,并添加描述
parser = argparse.ArgumentParser(description='命令行中传入一个数字')
# 添加一个位置参数 'integers',指定其数据类型和帮助信息
parser.add_argument('integers', type=str, help='传入的数字')
# 解析命令行参数
args = parser.parse_args()
# 打印解析得到的参数对象
print(args)
要尝试运行这段代码,你可以按照以下步骤操作:
-
创建一个新的文件夹:在你的桌面或者任意你喜欢的位置创建一个新的文件夹命名为test_argparse,作为你实验的工作空间。
-
新建一个 Python 脚本文件:在你刚刚创建的文件夹中,新建一个
.py
文件,例如命名为testargparse.py
。 -
复制代码到文件中:将上述示例代码复制到你刚新建的 Python 脚本文件中。
继续之前的步骤,完成代码的运行,可以按照如下指导进行: -
打开命令行界面:在 macOS 中打开“终端”应用,Windows 用户则可以打开“命令提示符”或“PowerShell”。
-
切换到工作目录:使用
cd
命令将命令行界面的当前工作目录切换到包含你的.py
文件的文件夹中。如果你的文件夹位于桌面,并且名为test_argparse
,可以使用如下命令:- 在 macOS 或 Linux 上:
~/Desktop/test_argparse 这样的命令时,~ 不是省略的意思,而是一个实际可以使用的符号,它会被自动扩展为当前用户的主目录的完整路径。
cd ~/Desktop/test_argparse
- 在 Windows 上:
cd %USERPROFILE%\Desktop\test_argparse
-
运行脚本:最后,针对你的脚本,使用 Python 命令加上脚本名称来运行它。如果你想查看
argparse
自动生成的帮助信息,可以加上-h
或--help
参数,这将展示你定义的命令行参数的帮助信息,而不实际运行脚本的其他部分。先执行 -h的目的就是让用户知道帮助信息,这样用户才能知道到底需要补充或者是赋予哪些参数基于代码进行执行python testargparse.py -h
运行结果如下(当然这是我的运行环境和你们的可能有些差异):
注意注意这里是重点
可以返回的信息是这样的:
usage: testargparse.py [-h] integers
命令行中传入一个数字 # 这是之前设定的描述内容
positional arguments: # 位置参数 名字是 integers 咱们之前设定的提示信息传入的数字
integers 传入的数字
optional arguments: # 可选参数 -h, --help 由于没有设定所以只有两个基础的
-h, --help show this help message and exit
因此,基于之前的讲解需要在命令行界面赋予integers参数一个数值,只需要按位置赋值就可以了,只有一个。所以需要在命令行中这样执行
python testargparse.py 参数值(自己设定我这里用123举例子)
(base) wangyang@wangyangdeMBP argparse % python testargparse.py 123
Namespace(integers='123')
提示代码运行时采用的integers=‘123’
- 操作args字典
在使用argparse
模块解析命令行参数后,得到的确实是一个Namespace
对象。这个对象在外观和用法上类似于 Python 字典,但其实是一个简单的对象实例,允许通过属性访问的方式来获取参数值,而不是字典那样通过键(key)来访问值。
Namespace
对象
Namespace
对象是 argparse
用来存储解析出来的命令行参数值的容器。每个通过 add_argument
方法定义的命令行参数都会成为 Namespace
对象的一个属性。所以,在您的例子中,integers
参数被解析后存储在 args
对象中,可以通过 args.integers
来访问。
使用案例
根据您的描述,下面的代码展示了如何使用 argparse
来定义、解析命令行参数,并通过属性访问方式读取参数值:
import argparse
# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(description='命令行中传入一个数字')
# 定义一个位置参数 'integers'
parser.add_argument('integers', type=str, help='传入的数字')
# 解析命令行参数
args = parser.parse_args()
# 获得并打印 'integers' 参数
print(args.integers)
命令行运行指令
当在命令行中运行 python demo.py 123
时,您正确地指出,输出结果将是:
123
这个结果验证了 integers
参数被成功解析并通过 args.integers
访问的过程。
深度学习中调用参数这是通过这样方式实现使用的
8.传入多个参数
当需要通过命令行向 Python 脚本传递多个参数时,可以使用 argparse
模块的 nargs
参数来实现。nargs
参数允许您指定一个命令行参数应该接收多少个值。这对于接受可变数量的参数特别有用。
以下是一些使用 nargs
的不同方式,以及它们的含义:
nargs='+'
:参数至少需要一个值,没有提供值会报错。nargs='*'
:参数可以有任意个值,包括零个。nargs='?'
:参数要么没有值(这时使用默认值,如果有的话),要么有一个值。nargs=N
(其中 N 是一个整数):参数正好需要 N 个值。
假设您有一个脚本 demo.py
,您希望它接受一个名为 integers
的参数,该参数可以传入一个或多个整数值。您可以这样定义 argparse
解析器:
import argparse
parser = argparse.ArgumentParser(description="从命令行接收多个数字。")
parser.add_argument('integers', nargs='+', type=int, help="一个或多个整数")
args = parser.parse_args()
print(args.integers)
在这个例子中,由于设置了 nargs='+'
,所以 integers
参数可以接收一个或多个整数。如果你运行这个脚本并传入多个整数,比如 python demo.py 1 2 3 4
,输出将是:
[1, 2, 3, 4]
这表明 integers
参数成功接收了多个命令行参数,并且它们被存储在一个列表中,通过 args.integers
访问。这种方式使得处理和操作命令行输入的可变数量数据变得方便而直接。
4.1 IDE执行
上文中主要解释了在交互式界面下如何使用。接下来对IDE环境下讲解,如何和传统的.py文件一样进行运行,则代码会报错,我们看一下报错结果:
那么是否这样就只能在命令行界面执行代码呢。以下是几种解决方式:
- 直接这样运行很傻瓜 ,直接在vscode中的终端在输入命令行指令。图裤子放屁的解决方式
- pycharm
打开你的 Python 脚本。在菜单栏上,点击 Run -> Edit Configurations…。在打开的 Run/Debug Configurations 对话框中,找到 Script parameters 或 Parameters 文本框。在 Script parameters 文本框中输入你的命令行参数,参数之间用空格分隔,如 42。点击 OK 来保存配置,然后运行你的脚本。 - vscode
在 VS Code 中打开你的 Python 脚本。
在左侧活动栏中,点击 Run and Debug(播放按钮图标),或者从 View 菜单选择 Run。就是左侧的三角形▶️
点击页面顶部的 Create a launch.json file,选择 Python 环境。
接着点底下这个带有参数的pyhon文件
在生成的 launch.json 文件中,找到 “args”: [] 部分,将你的命令行参数作为字符串元素添加到数组中,如:
保存 launch.json 文件并关闭。
注意这个仅限于调试文件,所以运行要使用
可以通过Run and Debug 侧栏或者 F5 键来运行你的脚本
确保将上述示例中的 42 替换为你的实际参数。
通过在 IDE 的运行 / 调试配置中设置命令行参数,你就可以在 IDE 内部运行需要这些参数的脚本了。IDE 会在启动脚本时自动将这些参数传递给它,就像在命令行中运行脚本时手动输入参数一样。
- 将代码参数改成可选在IDE下运行
其实只需要将位置参数,改为可选参数就行。根据上文中的给出的代码示例,integers
参数是作为一个位置参数定义的,它在命令行执行时是必需的。若要改为可选参数,做一些调整。
为了让 integers
参数变为可选的,并且能够在 IDE 中运行而不报错(即使没有指定参数),
import argparse
parser = argparse.ArgumentParser(description='命令行中传入一个数字')
# 修改参数定义为可选的,通过 '--integers' 来指定
parser.add_argument('--integers', type=str, required=False, default="默认值", help='传入的数字')
args = parser.parse_args()
# 获得传入的参数
print(args.integers)
在这个修改之后的版本中,使用 --integers
来指定参数,可以使它变为可选的。这里还添加了参数 ,以及 default="默认值"
,用于指定当该参数没有被明确提供时的默认值。这样做的话,无论是否在命令行中提供了 --integers
参数,您的脚本都能正常运行。仅需要对默认值进行修改就可以直接使用了。需要修改参数的时候对可选参数的默认值进行修改。直接调用使用。
5. 总结
许多深度学习项目提供的代码示例往往是基于命令行交互式界面设计的。在尝试运行这些代码时,我也遇到了不少难题,经历了一系列的尝试和调整。通过这个过程,我学习到了各种操作和技巧来修改代码,使其能够正常执行。我在这里留下了一些技巧和知识,希望对你遇到的问题提供帮助。坚持下去,加油!
如果你在学习或运行代码过程中有任何疑问或困难,欢迎随时向我提问,我会尽快更新内容来解答你的疑惑。一起努力,探索深度学习的奥秘!