• Python | 执行shell 命令的几种方法


    本文总结使用 shell 脚本的几种方法。

    Updated: 2022 / 7 / 27


    Python | 执行shell脚本的几种方法


    总览

    Python 作为一门脚本语言,有时候需要与 shell 命令交互式使用,在 Python 中提供了很多的方法可以调用并执行 shell 脚本,本文做一个简单的总结 1

    本文的开发环境是 macOS Big Sur


    方法

    os

    • os.system('command')
      这是 python 自带的执行 shell 命令的方法,其中最后一个 0 是这个命令的返回值,为 0 表示命令执行成功。
      但是使用 system() 无法将执行的结果保存起来,如下所示:
    print(os.system("touch a.txt"))
    # 0
    # 
    # 会返回一个 0,表示执行成功了,然后在当前文件夹之下创建了一个新的 a.txt 文件
    
    print(os.system("ls -lh"))
    # total 416
    # -rw-r--r--  1   staff    49B Jul 27 20:02 main.py
    # -rw-r--r--  1   staff    63B Jul 16 17:38 temporary.py
    # -rw-r--r--  1   staff   4.1K Jul 24 20:02 test.py
    # -rw-r--r--  1   staff    94B Jul 24 19:31 usrs_info.pickle
    # 0
    #
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    • os.popen('command')
      通过 os.popen() 返回的是一个文件对象,对其进行读取 read() 的操作可以看到执行的输出。
    f = os.popen("ls -l")
    # 返回的是一个文件对象
    print(f.read())
    # 通过文件的read()读取所返回的内容
    # 
    #
    # total 416
    # -rw-r--r--  1   staff    49B Jul 27 20:02 main.py
    # -rw-r--r--  1   staff    63B Jul 16 17:38 temporary.py
    # -rw-r--r--  1   staff   4.1K Jul 24 20:02 test.py
    # -rw-r--r--  1   staff    94B Jul 24 19:31 usrs_info.pickle
    
    f = os.popen("touch b.txt")
    # 创建一个文件
    print(f.read())
    # 无返回值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Subprocess

    subprocess 模块是 python2.4 版本开始引入的模块,也是系统自带的,不需要再额外安装了。

    主要用来取代一些旧的模块方法,如 os.systemos.spawn*os.popen*commands.* 等。

    subprocess 通过子进程来执行外部指令,并通过 input / output / error 管道,获取子进程的执行的返回信息。


    1. subprocess.call()

    执行命令,并返回执行状态。其中,

    • shell 参数为 False 时,命令以及命令的参数需要通过列表的方式传入;
    print(subprocess.call(["ls", "-l"], shell=False))  
    # 
    #
    # total 416
    # -rw-r--r--  1   staff    49B Jul 27 20:02 main.py
    # -rw-r--r--  1   staff    63B Jul 16 17:38 temporary.py
    # -rw-r--r--  1   staff   4.1K Jul 24 20:02 test.py
    # -rw-r--r--  1   staff    94B Jul 24 19:31 usrs_info.pickle
    # 0
    
    print(subprocess.call(["touch", "c.txt"], shell=False))
    # 直接返回 0,表示操作成功
    # 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • shell 参数为 True 时,可通过一个字符串直接传入命令以及命令所需要的参数;
    print(subprocess.call(("ls -l"), shell=True)
    # 
    # 
    # total 416
    # -rw-r--r--  1   staff    49B Jul 27 20:02 main.py
    # -rw-r--r--  1   staff    63B Jul 16 17:38 temporary.py
    # -rw-r--r--  1   staff   4.1K Jul 24 20:02 test.py
    # -rw-r--r--  1   staff    94B Jul 24 19:31 usrs_info.pickle
    # 0
    
    print(subprocess.call(["mkdir newdir1"], shell=True))  
    # 直接返回 0,表示操作成功
    # 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1. subprocess.check_call()
      用法与 subprocess.call() 类似,区别是,
      当返回值不为 0 时,直接抛出异常。

    1. subprocess.check_output()
      用法与上面两个方法类似,区别是,
      当返回值为 0 时,直接返回输出结果;
      当返回值不为 0,直接抛出异常。
      需要说明的是,该方法在 python3.x 中才有。
    a = subprocess.check_output(["ls","-l"], shell=False)
    print(a)  
    # 
    # 不是直接返回0了,而是直接返回执行结果的内容
    # b'total 416\n-rw-r--r--  1 xueshanzhang  staff    4326 Jul 24 17:59 MotivationLetterGenerator.py\ndrwxr
    
    • 1
    • 2
    • 3
    • 4
    • 5

    subprocess 的功能还有更多,比如还有 Popen 类。

    subprocess 模块中定义了一个 Popen 类,通过它可以来创建进程,并与其进行复杂的交互。


    sh

    首先安装 sh 库,pip install sh

    Python 是一种伟大的脚本语言,不过有时使用标准 ossubprocess 库会有点棘手。

    sh 库提供了一种不错的替代方案。sh 库:http://amoffat.github.io/sh/

    库允许用户像使用普通函数一样调用任意程序,这对自动化工作流和任务非常有用。

    它的一般工作模式如下:

    sh.command_name("参数一", "参数二", "参数三")
    
    • 1

    如下,

    print(sh.pwd())
    # /Users/PycharmProjects/pythonProject0312
    
    sh.mkdir('FolderA')
    
    sh.touch('File.txt')
    
    print(sh.whoami())
    # your username
    # 
    # 
    
    print(sh.echo('This is great!'))
    # This is great!
    # 
    # 
    
    sh.ls("-l")
    # 等价于 ls -l
    print(sh.ls("-l"))
    # total 416
    # -rw-r--r--  1   staff    49B Jul 27 20:02 main.py
    # -rw-r--r--  1   staff    63B Jul 16 17:38 temporary.py
    # -rw-r--r--  1   staff   4.1K Jul 24 20:02 test.py
    # -rw-r--r--  1   staff    94B Jul 24 19:31 usrs_info.pickle
    
    sh.df("-h")  
    # 等价于 df -h
    print(sh.df("-h"))
    # Filesystem       Size   Used  Avail Capacity iused      ifree %iused  Mounted on
    # /dev/disk3s1s1  228Gi   21Gi   31Gi    41%  553757 2393071203    0%   /
    # devfs           204Ki  204Ki    0Bi   100%     705          0  100%   /dev
    # ...
    # 
    # 
    
    sh.du("-h", "-d 1")
    # 等价于 du -h -d 1
    print(sh.du("-h", "-d 1"))  
    # 当有多个参数的情况,且参数可以赋值
    #   0B	./FolderA
    #  92K	./.git
    #  40K	./.idea
    # 340K	.
    # 
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    注意:上面在通过 sh.** 编写的时候可能没有代码提示,因为 sh 模块里面并没有直接定义像上面的 pwd()touch()du() 等这些函数,他是通过其他的方式实现的,所以没有智能敏感提示。


    参考链接


    1. python执行shell脚本的几种方法 ↩︎

  • 相关阅读:
    3分钟让你学会axios在vue项目中的基本用法(建议收藏)
    3 款非常实用的 Node.js 版本管理工具
    141.环形链表
    关于安卓唯一标识的汇总及最佳做法
    正则表达式如何匹配 空字符串““
    十二、【漏洞复现】Rails任意文件读取(CVE-2019-5418)
    简述@RequestParam与@RequestBody参数注解
    【Debian】Debian10.0.0安装选项问答
    基于 Python 中的值对计数器进行排序
    大模型LLM 在线量化;GPTQ\AWQ量化及推理
  • 原文地址:https://blog.csdn.net/MissMango0820/article/details/126021826