python subprocess执行shell命令

2023-05-16

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

subprocess的目的就是启动一个新的进程并且与之通信。

subprocess模块中只定义了一个类: Popen。可以使用Popen来创建进程,并与进程进行复杂的交互。它的构造函数如下:

class subprocess.Popen( args, 
      bufsize=0, 
      executable=None,
      stdin=None,
      stdout=None, 
      stderr=None, 
      preexec_fn=None, 
      close_fds=False, 
      shell=False, 
      cwd=None, 
      env=None, 
      universal_newlines=False, 
      startupinfo=None, 
      creationflags=0)

参数args可以是字符串或者序列类型(如:list,元组),用于指定进程的可执行文件及其参数。如果是序列类型,第一个元素通常是可执行文件的路径。我们也可以显式的使用executeable参数来指定可执行文件的路径。

subprocess.Popen(["cat","test.txt"])
subprocess.Popen("cat test.txt")
这两个之中,后者将不会工作。因为如果是一个字符串的话,必须是程序的路径才可以。(考虑unix的api函数exec,接受的是字符串
列表)
但是下面的可以工作
subprocess.Popen("cat test.txt", shell=True)
这是因为它相当于
subprocess.Popen(["/bin/sh", "-c", "cat test.txt"])
在*nix下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的
话,会被当做是可执行文件的路径,这样就不能传入任何参数了。

注意:
shlex.split()可以被用于序列化复杂的命令参数,比如:

>>> shlex.split('ls ps top grep pkill')
['ls', 'ps', 'top', 'grep', 'pkill']
>>>import shlex, subprocess
>>>command_line = raw_input()
/bin/cat -input test.txt -output "diege.txt" -cmd "echo '$MONEY'" 
>>>args = shlex.split(command_line)
>>> print args
['/bin/cat', '-input', 'test.txt', '-output', 'diege.txt', '-cmd', "echo '$MONEY'"]
>>>p=subprocess.Popen(args)

可以看到,空格分隔的选项(如-input)和参数(如test.txt)会被分割为列表里独立的项,但引号里的或者转义过的空格不在此列
。这也有点像大多数shell的行为。

在*nix下,当shell=True时,如果arg是个字符串,就使用shell来解释执行这个字符串。如果args是个列表,则第一项被视为命令,
其余的都视为是给shell本身的参数。也就是说,等效于:
subprocess.Popen(['/bin/sh', '-c', args[0], args[1], ...])

参数bufsize一般0 无缓冲,1 行缓冲,其他正值 缓冲区大小,负值 采用默认系统缓冲(一般是全缓冲)

executable一般不用,args字符串或列表第一项表示程序名

参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。

如果参数shell设为true,程序将通过shell来执行。

参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。

subprocess.PIPE
  在创建Popen对象时,subprocess.PIPE可以初始化stdin, stdout或stderr参数。表示与子进程通信的标准流。

subprocess.STDOUT
  创建Popen对象时,用于初始化stderr参数,表示将错误通过标准输出流输出。

Popen的方法:

Popen.poll()
  用于检查子进程是否已经结束。设置并返回returncode属性。

Popen.wait()
  等待子进程结束。设置并返回returncode属性。

Popen.communicate(input=None)
  与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。

Popen.send_signal(signal)
  向子进程发送信号。

Popen.terminate()
  停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。

Popen.kill()
  杀死子进程。

Popen.pid
  获取子进程的进程ID。

Popen.returncode
  获取进程的返回值。如果进程还没有结束,返回None。

进程通信:

如果想得到进程的输出,管道是个很方便的方法:

p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)  
(stdoutput,erroutput) = p.communicate()  

p.communicate会一直等到进程退出,并将标准输出和标准错误输出返回,这样就可以得到子进程的输出了。

上面的例子通过communicate给stdin发送数据,然后使用一个tuple接收命令的执行结果。

上面,标准输出和标准错误输出是分开的,也可以合并起来,只需要将stderr参数设置为subprocess.STDOUT就可以了,这样子:

p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)  
(stdoutput,erroutput) = p.communicate()  

如果你想一行行处理子进程的输出,也没有问题:

p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)  
while True:  
    buff = p.stdout.readline()  
    if buff == '' and p.poll() != None:  
        break  

死锁

但是如果你使用了管道,而又不去处理管道的输出,那么小心点,如果子进程输出数据过多,死锁就会发生了,比如下面的用法:

p=subprocess.Popen("longprint", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)  
p.wait()  

longprint是一个假想的有大量输出的进程,那么在我的xp, Python2.5的环境下,当输出达到4096时,死锁就发生了。当然,如果我们用p.stdout.readline或者p.communicate去清理输出,那么无论输出多少,死锁都是不会发生的。或者我们不使用管道,比如不做重定向,或者重定向到文件,也都是可以避免死锁的。

subprocess还可以连接起来多个命令来执行。
在shell中我们知道,想要连接多个命令可以使用管道。
在subprocess中,可以使用上一个命令执行的输出结果作为下一次执行的输入。例子如下:

转载于:https://my.oschina.net/u/2000675/blog/727694

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python subprocess执行shell命令 的相关文章

随机推荐

  • Lua Table 长度的计算

    计算 Lua 的 Table长度 在 Lua 中 xff0c 我们可以通过这个符号 来计算字符串的长度和一个table的长度 xff0c 比如 xff1a str 61 34 I 39 am a string 34 print str 61
  • Mybatis-Plus 之BaseMapper 方法详解

    为什么80 的码农都做不了架构师 xff1f gt gt gt Mapper 继承该接口后 xff0c 无需编写 mapper xml 文件 xff0c 即可获得CRUD功能 这个 Mapper 支持 id 泛型 64 author hub
  • mac上面查看路由表

    为什么80 的码农都做不了架构师 xff1f gt gt gt 问题 本来想使用linux上面的命令route n查看mac上面的路由表的 xff0c 结果显示mac上面的route命令不是这样玩的 解决 netstat nr Mac上面需
  • el-select使用方法及遇到数据回显的坑

    2019独角兽企业重金招聘Python工程师标准 gt gt gt lt el select v model 61 34 temp lang 34 class 61 34 filter item 34 placeholder 61 34 P
  • 中国电话号码格式

    中国区号 086 北京区号010 我的电话123456 填在表格上应该如何填写呢 xff1f 手机号码应该如何填写呢 xff1f xff1f 00就不必写了 xff0c 写 43 就好了 xff0c 不同的国家国际接入的号不太一样的 xff
  • 【Quick-Cocos2d-x笔记】【一】Mac环境及相关配置

    本来是老老实实的想 xff0c 一心一意的先把C 43 43 学好 xff0c 在觉得自己C 43 43 水平还是菜鸟级的时候不要去动其他的东西 但自上次面试回来时候 xff0c 觉得这样不行啊 xff0c 虽然说现在从事的是C 43 43
  • matlab练习程序(粒子群优化PSO)

    算法没有和图像处理直接相关 xff0c 不过对于图像分类中的模式识别相关算法 xff0c 也许会用到这个优化算法 算法步骤 xff1a 1 首先确定粒子个数与迭代次数 2 对每个粒子随机初始化位置与速度 3 采用如下公式更新每个粒子的位置与
  • 您需要来自administrators的权限才能对此文件进行更改

    今天我重装了系统 xff0c 以前D盘里的一个文件夹想删除 xff0c 可以一直没法删除 xff0c 原先它提示 您需要来自 S 1 5 21 602162358 1284227242 682003330 500 的权限才能对此文件夹 xf
  • ***JAVA多线程的应用场景和应用目的举例

    多线程使用的主要目的在于 xff1a 1 吞吐量 xff1a 你做WEB xff0c 容器帮你做了多线程 xff0c 但是他只能帮你做请求层面的 简单的说 xff0c 可能就是一个请求一个线程 或多个请求一个线程 如果是单线程 xff0c
  • Kafka遇到30042ms has passed since batch creation plus linger time at org.apache.kafka.clients.producer...

    问题描述 xff1a 运行生产者线程的时候显示如下错误信息 xff1a Expiring 1 record s for XXX 0 30042 ms has passed since batch creation plus linger t
  • tcpdump -w 和 -r 的使用

    tcpdump的说明文档是这样的 xff1a w 将原始的信息包写入 形式如 tcpdump w tmp result txt 我今天试了一下 xff0c 发现其写成的文件如果用cat vim来查看的话 xff0c 都显示为乱码 经过man
  • 如何用Go访问深层嵌套的JSON数据?

    原文来自https hashnode com post how 大多数情况下 xff0c 开发人员需要使用来自其他服务的JSON数据并对其进行查询 查询JSON文档非常耗时 在过去的几天里 xff0c 我正在为Golang编写一个包 xff
  • Identity Card

    Identity Card Time Limit 2000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 995 Accepted
  • 华为S5700交换机开启WEB配置

    近来很多朋友问关于S5700开启WEB不成功的问题 xff0c 现整理出具体步骤和命令 提示 xff1a 华为交换机配置时 xff0c 输入命令前几个字母 xff0c 按TAB可以自动补全命令 xff0c 比如在系统视图下输入sh按下TAB
  • 托管堆上对象的大小(Size)和Layout

    前几天 xff0c 我介绍了托管环境下struct实例的Layout和Size xff0c 其中介绍了StructLayoutAttribute特性 xff0c 其实StructLayoutAttribute特性不只可以用在struct上
  • 网上十大黑客软件大曝光

    网上十大黑客软件大曝光 Internet网上的黑客网站多如牛毛 xff0c 黑客软件也越来越多 越来越黑 笔者现将这些黑客软件分门别类地曝一曝光 xff0c 并提出相应的解决方案 xff0c 以防患于未然 一 古老的WinNuke 平台 x
  • C# DataSet和DataTable详解[转]

    1 创建DataSet对象 xff1a DataSet ds 61 new DataSet 34 DataSetName 34 2 查看调用SqlDataAdapter Fill创建的结构 da Fill ds 34 Orders 34 D
  • 【Python】爬取网站图片

    import requests import bs4 import urllib request import urllib import os hdr 61 39 User Agent 39 39 Mozilla 5 0 X11 Linu
  • 纯C++实现的HTTP请求(POST/GET)

    纯C 43 43 实现的HTTP请求 xff08 POST GET xff09 xff0c 支持windows和linux xff0c 进行简单的封装 xff0c 方便调用 实现如下 xff1a include 34 HttpConnect
  • python subprocess执行shell命令

    2019独角兽企业重金招聘Python工程师标准 gt gt gt subprocess的目的就是启动一个新的进程并且与之通信 subprocess模块中只定义了一个类 Popen 可以使用Popen来创建进程 xff0c 并与进程进行复杂