美文网首页生信Python学习
Python 命令行(一)- 概念与入门

Python 命令行(一)- 概念与入门

作者: 山药鱼儿 | 来源:发表于2021-06-14 17:44 被阅读0次

    在工作中,我们通常会选择使用 Python 语言来编写命令行,以代替 Shell 脚本来解决系统管理的问题。Python 既可以当作脚本语言来使用,也可以用以编写大型的服务;而作为脚本语言使用时,Python 提供了很多功能来编写命令行工具,并且很多的 Python 开源项目也可以用来快速构建命令行工具。

    Python 命令行 系列文章,将对 Python 命令行工具的构建展开介绍,大纲如下:

    • Python 标准库提供的命令行工具
    • ini 格式的配置文件解析
    • Python 解析命令行参数
    • 标准库 logging 的使用
    • 使用开源项目快速构建强大的命令行工具

    下面,我们就开始第一部分 Python 标准库提供的命令行工具 的学习吧~

    获取命令行参数 - sys.argv

    """test_argv.py"""
    from __future__ import print_function
    import sys
    
    print(sys.argv)
    

    运行结果:

    print(sys.argv)

    sys.argv 列表保存了所有的命令行参数,第一个参数为命令行程序的名称,其余参数均以字符串的形式保存在该列表中。sys.argv 是一个保存命令行参数的普通列表,因此我们在程序中可以对该列表进行修改:

    """
    test_argv.py
    sys.argv is a list, so we can modify it.
    """
    from __future__ import print_function
    import os
    import sys
    
    
    def main():
        sys.argv.append("")
        filename = sys.argv[1]
        if not os.path.isfile(filename):
            raise SystemExit('{} does not exist.'.format(filename))
        elif not os.access(filename, os.R_OK):
            raise SystemExit('{} is not accessible.'.format(filename))
        else:
            print('Get {}!'.format(filename))
            
    
    if __name__ == '__main__':
        main()
    

    上面的代码,从命令行获取文件名称,然后判断文件是否存在,以及是否可读。其中,我们使用 sys.argv[1] 来获取文件名称,为避免没有传参而是直接运行程序,造成的 sys.argv[1] 索引越界,我们在程序的开始,向 sys.argv 中添加了一个空字符串。

    运行结果:

    相当于访问一个不存在的文件 访问一个存在并可达的文件 访问一个没有读权限的文件

    注:上述第一次和第三次的运行结果,退出状态都是 1 ,而只有在访问存在并可读的文件时,退出状态才为 0 。这是因为, SystemExit 不仅可以在退出时打印错误信息,还会以非 0 的返回码退出程序。

    读取标准输入 - sys.stdin fileinput

    sys.stdin

    我们知道 Shell 脚本独特的一个优点就是管道,管道可以连接不同的 Linux 指令,使用管道我们可以用多个简单的命令来实现一个复杂的功能。因此,工作当中,我们通常也会使用管道来结合 Python 语言和 Shell 脚本的优势。

    在 Python 标准库的 sys 库中,具有三种文件描述符:标准输入(sys.stdin)、标准输出(sys.stdout)和标准错误(sys.stderr)。如:下面的代码从标准输入读取内容,并打印到命令行终端:

    from __future__ import print_function
    import sys
    
    for i,line in enumerate(sys.stdin):
        print("line {}: {}".format(i, line), end="")
    

    运行结果:

    sys.stdin 从标准输入读取内容

    sys.stdin 其实是一个普通文件对象,除了从标准输入读取内容外,我们也可以使用 sys.stdin 调用文件对象的方法:

    from __future__ import print_function
    import sys
    
    def get_content_lines():
        return sys.stdin.readlines()
    
    def get_content():
        return sys.stdin.read()
    
    def main():
        sys.argv.append("")
        if not sys.argv[1]:
            print(get_content_lines())
        else:
            print(get_content())
            
    if __name__ == "__main__":
        main()
    

    运行结果:

    sys.stdin.readlines、sys.stdin.read

    fileinput

    熟悉 Linux 系统的同学想必对 awk 都很熟悉,awk 功能强大,但语法复杂,小编是一直都记不住... ... 不过,有了 sys.stdin ,我们完全可以不使用 awk 语言,原因有以下两点:

    • Python 命令可以和 Linux 下的管道进行较好地结合;
    • Python 语言具有比 awk 应用领域广泛、可读性好、功能强大、语法清晰等诸多优点;
    • Python 标准模块 fileinput 可以支持多文件处理。

    因此,我们完全可以在 Linux 下使用 Python 代替 awk 进行数据处理。上面提到 fileinput 支持多文件处理,接下来我们就来详细介绍下 fileinput 的使用。

    fileinput 提供了比 sys.stdin 更加通用的功能:

    • fileinput 会遍历 sys.argv[1:] 列表,依次读取命令行参数给出的多个文件;
    • 如果列表为空,则 fileinput 将会从标准输入中读取内容。

    调用 fileinput.input() 方法即可按行读取内容:

    from __future__ import print_function
    import fileinput
    
    for num, line in enumerate(fileinput.input()):
        print("LINE {}: {}".format(num, line), end="")
    

    运行结果:

    fileinput 可以从标准输入读取数据 fileinput 从 sys.argv 中读取多个文件

    fileinput 除了支持读取多个文件,也提供了一些方法,以便返回当前读取的内容属于哪一个文件,fileinput 中常用的方法如下:

    方法 用途
    filename 当前读取的文件名
    fileno 文件的描述符
    filelineno 正在读取的行是当前文件的第几行
    isfirstline 正在读取的行是否是当前文件的第一行
    isstdin 正在读取文件还是直接从标准输入读取内容

    下面是一个例子:

    from __future__ import print_function
    import fileinput
    
    for line in fileinput.input():
        metadata = [fileinput.filename(), fileinput.fileno(), fileinput.filelineno(), fileinput.isfirstline(), fileinput.isstdin()]
        if metadata[3]:
            print("\n=============================\n")
        print(*metadata, end=" ")
        print(line, end="")
    

    运行结果:

    fileinput 常用方法

    错误信息 - SystemExit

    本篇文章前面的篇幅主要讨论了,Python 如何从标准输入读取内容。下面我们将介绍如何向标准输出及错误输出中写入内容。与标准输入类似,我们借助 sys.stdout sys.stderr 即可:

    import sys
    
    sys.stdout.write('Hi\n')
    sys.stderr.write('Mia\n')
    

    首先,我们将标准输出从定向到 /dev/null ,则终端只剩下标准错误:

    标准输出从定向到 /dev/null

    下面,我们将标准错误从定向到 dev/null,则终端只剩下标准输出:

    将标准错误重定向到 /dev/null

    或者可以使用 Jupyter Notebook 来查看运行结果,更为直观:


    标准输出和标准错误

    注意:在实际工作中,一般情况下都不会直接调用 stdout.write 来输出内容,因为 print 函数默认输出到命令行终端。

    当 Python 程序执行失败时,通常需要在标准错误中输出错误信息,然后以非零的返回码退出程序。常见的做法有以下两种:

    sys.stderr + sys.exit(1)

    import sys
    
    sys.stderr.write('error message.')
    sys.exit(1)
    

    运行结果:

    raise SystemExit("error message.")

    raise SystemExit('error message.')
    

    运行结果:

    读取密码 - getpass

    等待用户输入密码 打印用户名及密码

    总结:getpass 是一个非常简单的 Python 标准库,主要包含 getuser 函数 和 getpass 函数。前者用来从环境变量中获取用户名,后者用来等待用户输入密码。

    相关文章

      网友评论

        本文标题:Python 命令行(一)- 概念与入门

        本文链接:https://www.haomeiwen.com/subject/pvwneltx.html