📜  使用Python的argparse创建命令行实用程序

📅  最后修改于: 2020-08-28 04:53:12             🧑  作者: Mango

介绍

大多数面向用户的软件都带有视觉上令人愉悦的界面或通过装饰的网页。在其他时候,程序可能很小,以至于不能保证整个图形用户界面或Web应用程序都能将其功能展示给最终用户。

在这些情况下,我们可以构建可通过命令行界面或CLI 访问的程序。

在本文中,我们将探索Python的argparse模块,并使用它构建一个简单的命令行工具,以帮助我们快速缩短URL。

命令行界面

命令行接口是基于文本的用户界面,提供通过文本命令的计算机进行交互的方法。通过暴露接口来促进这种交互的程序被称为命令行解释器shell

它以文本输入的形式接收命令,根据提供的输入执行程序,然后在界面上显示输出。有许多可用的shell,其中最流行的是用于基于Unix的系统的Bourne shellC shell。的伯恩再次壳牌(又名bash)的是Bourne Shell中的一个非常受欢迎的延伸,沿着Korn外壳(KSH)。

同样值得注意的是,CLI与其他软件一样,需要用户帐户才能使用。系统对这些用户强制执行权限,以帮助控制访问级别以及用户可以通过系统实现的限制。由于外壳是用户和控制所有计算机操作的操作系统内核之间的接口,因此需要这种区别。需要限制对此功能的访问,以防止恶意使用命令行界面。

CLI提供提示,通常是一个美元符号($),指示您可以输入命令。但是,此提示还表示将在没有root用户访问权限的情况下执行输入的命令。

当授予与CLI交互的当前用户root访问权限时,提示将更改为井号(#)。

虽然图形用户界面(GUI)的更容易学习和视觉上更加直观,允许的CLI用户只使用键盘,这可能会导致更快的性能软件进行交互。与GUI相比,CLI占用的计算机资源也更少,从而使其更轻便,更快。

脚本编写

大多数命令行解释器附带一些基本命令,可以通过命令行界面调用所有基本命令来执行特定任务。一些常见的包括:

  • uptime:表示计算机已开启多长时间
  • date:返回当前日期和时间
  • ls:返回目录中所有文件和文件夹的列表
  • cd:用于从一个目录移动到另一个目录
  • pwd:用于显示当前工作目录
  • man:用于显示任何命令的手册或说明
  • touch:用于创建新的空文件
  • mkdir:用于创建新目录

Shell脚本是一种旨在由命令行解释器执行的程序。它包含一系列命令(例如上面列出的命令)以及变量和条件,这些条件和条件指示Shell执行哪些任务。

通过shell脚本,用户可以快速连续执行多个命令,而无需记住所有命令。它们通常用于实现重复性操作而无需重复输入命令,因此减少了最终用户所需的工作量。

我们可以编写包含要执行的Shell命令的Shell脚本,但是,我们也可以执行其他高级语言,例如Python和JavaScript。

什么是argparse

Python Shell脚本只是由命令行解释器执行的普通Python程序。执行shell脚本时,参数会通过sys.argv传递到我们的脚本中。此变量是传递给我们程序的参数的列表,包括脚本名称,它也是第一个参数。

通常,我们可以编写一个不需要任何额外参数的简单脚本,例如显示当前日期的简单脚本。但是,这将限制我们可以提供的功能。为了使脚本更具通用性并扩大其使用范围,我们必须通过自变量来促进自定义,这些自变量可为用户提供更多的功能方面的控制和选项。

argparse模块帮助我们解析与脚本一起传递的参数,并以更方便的方式处理它们。它还添加了自定义功能,例如以更简单的方式命名程序和添加描述。

argparse还为我们提供了一种自定义脚本使用说明的方法,并指示哪些参数是必需的,哪些参数是可选的。为了探索所有这些功能以及更多功能,我们将在下一部分中构建自己的Python CLI实用程序。

演示申请

当前,如果我们要缩短URL,则需要启动浏览器并导航到URL缩短站点以执行此任务。我们的目标是通过可以随时在终端上启动的脚本来加速和增强此URL缩短过程。我们仅需将需要缩短的URL作为参数传递,并作为响应接收缩短的URL。

在此演示中,我们将使用Shorte.st作为我们的提供程序,因为它的API非常简单明了。

创建帐户后,我们可以转到“ 链接工具”部分,然后选择“ 开发人员API”。在这里,我们将找到访问令牌和脚本将用来缩短URL的URL。

一旦用户向我们的命令行实用程序提供了要缩短的URL,我们便会将URL 与访问令牌一起发送给Shorte.st API端点。响应将是我们缩短的URL和状态消息。

让我们首先创建一个虚拟环境并安装requests模块,我们将使用该模块将HTTP请求发送到API: 

$ mkdir pyshortener && cd pyshortener
$ virtualenv --python=python3 env --no-site-packages
$ source env/bin/activate
$ pip install requests

在上面的第一行中,我们实际上使用双与号(&&)将两个命令组合在一起。这使我们能够依次执行命令,除非第一个命令失败,否则将阻止第二个命令执行。

创建虚拟环境并激活它之后,我们将安装Python依赖项。

对于此演示,我们将首先构建缩短功能,然后将其功能包装argparse到最终脚本中:

import requests
from requests.exceptions import ConnectionError
import json

def shorten_url(url):
    try:
        response = requests.put("https://api.shorte.st/v1/data/url",
                                {"urlToShorten": url},
                                headers={"public-api-token": "[MY-API-TOKEN]"})

        api_response = json.loads(response.content)

        return {"status": api_response['status'],
                "shortenedUrl": api_response['shortenedUrl'],
                "message": "URL shortened successfully"}

    except ConnectionError:
        return {"status": "error",
                "shortenedUrl": None,
                "message": "Please ensure you are connected to the internet and try again."}

shorten_url(www.stackabuse.com)

我们的函数接收一个URL,并将其发送到Shorte.st API,然后返回缩短的URL。让我们www.stackabuse.com通过执行脚本来简化:

$ python pyshortener.py
{'status': 'ok', 'shortenedUrl': 'http://gestyy.com/w6ph2J', 'message': 'URL shortened successfully'}

如我们所见,我们的函数起作用了,但是输出却不理想。我们还必须在脚本本身中对URL进行硬编码,这为我们提供了固定的输入和输出。

我们将更进一步,允许用户在执行脚本时将URL作为参数传递。为此,我们现在将介绍argparse以帮助我们解析用户提供的参数:

import requests
from requests.exceptions import ConnectionError
import json
import argparse # Add the argparse import

def shorten_url(url):
    # Code stays the same...

# Create a parser
parser = argparse.ArgumentParser(description='Shorten URLs on the terminal')

# Add argument
parser.add_argument('--url', default="google.com", help="The URL to be shortened")
args = vars(parser.parse_args())
print(args)

在此版本的脚本中,我们不会调用shorten_url,而只是打印出捕获和解析的参数argparse

我们首先使用创建一个ArgumentParser对象argparse,该对象将保存将传递的参数转换为可以使用的Python数据类型所需的所有信息。

创建解析器后,我们现在可以使用添加参数parser.add_argument()。此函数允许指定有关参数的以下信息:

  • 第一个参数是用于标识我们的参数的名称或标志。可选参数由-前缀标识,在本例中--url为可选参数。
  • default当用户未提供参数时,该选项允许指定默认值。
  • help选项简要描述了参数是什么。
  • 我们还可以使用该choice选项为参数指定允许的值,例如yes和no。
  • 通过一个type选项,我们还可以指定命令将转换为的类型,例如将参数转换为整数。

在不提供任何参数的情况下运行脚本时,URL默认为“ google.com”,就像我们在add_argument方法中设置的一样:

$ python pyshortener.py
{'url': 'google.com'}

现在,当我们www.stackabuse.com使用--url标志传递时,将其设置为url键的值:

$ python pyshortener.py --url www.stackabuse.com
{'url': 'www.stackabuse.com'}

现在,我们可以通过命令行接收用户的URL,并通过修改脚本来缩短它:

if args.get('url'):
   print(shorten_url(args['url']))

当我们运行它并传递URL时,我们应该从Shorte.st API接收输出:

$ python pyshortener.py --url stackabuse.com
{'status': 'ok', 'shortenedUrl': 'http://gestyy.com/w6pk2R', 'message': 'URL shortened successfully'}

尽管我们的输出并不像我们想要的那样友好,但是让我们创建一个函数来以更理想的方式格式化输出:

def handle_output(result):
   """ Function to format and print the output
   """
   if result["status"] == "ok":
       print(f"{result['message']}. Your shortened URL is:\n"
             f"\t{result['shortenedUrl']}")
   elif result["status"] == "error":
       print(f"{result['message']}")

# Receive and process the argument
args = vars(parser.parse_args())

if args.get('url'):
   result = shorten_url(args['url'])
   handle_output(result)

当我们再运行一​​次脚本时:

$ python pyshortener.py --url www.stackabuse.com
URL shortened successfully. Your shortened URL is:
        http://gestyy.com/w6pk2R

由于增加了handle_output()功能,我们的输出现在更加用户友好。要查看如何argparse为脚本生成帮助文本,我们可以执行带有-h标志的脚本以显示帮助文本,如下所示:

$ python pyshortener.py -h
usage: pyshortener.py [-h] [--url URL]

Shorten URLs on the terminal

optional arguments:
  -h, --help  show this help message and exit
  --url URL   The URL to be shortened

结论

我们使用Python构建了一个Shell脚本,以帮助我们在终端上快速缩短URL。我们已经使用该argparse模块来解析传递到脚本中的参数,甚至在提供参数的情况下定义了默认值。

现在,我们的脚本还具有漂亮的帮助消息,可以使用模块-h生成的标志来显示该消息,这argparse意味着我们不必手动将其写下来。

下一步将是增强我们的脚本以接受URL列表或从文本文件读取URL,以促进URL的批量缩短。

该项目中脚本的源代码可以在Github上找到。