首页 > 编程语言 >Python subProcess库以及Popen类的使用

Python subProcess库以及Popen类的使用

时间:2022-10-14 13:55:06浏览次数:74  
标签:函数 stdout Python Popen subprocess PIPE call subProcess

subprocess库是一个十分强大且常用的库,它可以用来调用第三方工具(例如:exe、另一个python文件、命令行工具)。

1.常用函数
call() :执行由参数提供的命令,把数组作为参数运行命令。

retcode = subprocess.call(["ls", "-l"])
【注意1】 在Linux系统中上述代码运行没有问题,但是在windows中上述代码运行会报错:FileNotFoundError: [WinError 2] 系统找不到指定的文件。这是由于call函数的shell参数默认为False状态,这个状态windows下并不支持,需要修改shell为True状态:

retcode = subprocess.call("ls -l",shell=True)
【注意2】 call函数建议在Linux系统中使用,在Windows系统中有诸多限制。在Linux系统中,call函数会直接打印出参数运行后的结果,而赋值的是返回结果,而非运行结果。例如下面的运行结果,直接打印出目录,但r的值为0。

【注意3】 在Windows系统下使用call函数要注意命令的区别,例如:复制应该是“copy”而非“cp”。
错误代码:

subprocess.call(['cp', train_blur[index], os.path.join(args.output_path, 'train\\blur\\%s'%('_'.join(train_blur[index].split('\\')[-3:])))], shell=True)
正确代码:

subprocess.call(['copy', train_blur[index], os.path.join(args.output_path, 'train\\blur\\%s'%('_'.join(train_blur[index].split('\\')[-3:])))], shell=True)
【注意4】 在使用call函数的时候尽量不要使用shell的True参数,会造成安全上的问题。

※运行代码:

retcode = subprocess.call(["ls", "-l"])

check_call():和上面的call()作用相同,唯一的不同点在于对于返回值的处理上。
当call()函数和check_call()函数的返回值都为1的时候:

check_call()函数的返回值为1的时候会报错。并且check_call()函数会把运行结果赋值给变量,而call()函数会把返回值复制给变量。

check_output():和上面的两个函数作用相同,唯一的不同点是,这个函数可以获得返回的结果。


2. Popen模块
Popen():相较于上面的三个函数,popen()更加精细化,上面的三个函数都是父进程会等待子进程结束,但是popen()函数只有在使用 wait() 时才会等待。所以,上面的三个函数相当于,popen+wait的组合。

child = subprocess.Popen(['ping','-c','4','127.0.0.1'])
child.wait(4)
#或
child = subprocess.Popen('ping -c4 127.0.0.1',shell=True)
child.wait(4)
wait()还可以设置超时时间,超过时间父进程将就不在等待了。
结果如图:
Popen还有三个参数,分别为:stdin、stdout、stderr。
例如:

p2 = subprocess.Popen(["grep","0:0"],stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout是标准输出重定向;
stdin:我们可以看到,结果被储存进了subprocess.PIPE里,实际上,subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe),我们也可以利用这个特性,将stdout和stdin一起使用进行连续的输入输出:

c1 = subprocess.Popen(["uname","-a"], stdout=subprocess.PIPE)
c2 = subprocess.Popen(["wc"],stdin=child1.stdout,stdout=subprocess.PIPE)
out = c1.communicate()
print(out)
out = c2.communicate()
print(out)

subprocess.PIPE实际上为文本流提供一个缓存区。c1的stdout将文本输出到缓存区,随后c2的stdin从该PIPE中将文本读取走。c2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
stderr:不常用,返回错误信息,我们可一对其进行标准输出,例如:

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
【注意1】 communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成。

              communicate() 返回一个元组 (stdout_data, stderr_data) 。如果流以文本模式打开,则数据将是字符串;否则,字节。

        请注意,如果要将数据发送到进程的标准输入,则需要使用 stdin=PIPE 创建 Popen 对象。同样,要在结果元组中获得除 None 以外的任何内容,您还需要提供 stdout=PIPE 和/            或 stderr=PIPE

          如果进程在 timeout 秒后没有终止,则会引发 TimeoutExpired 异常。捕获此异常并重试通信不会丢失任何输出。

如果超时到期,子进程不会被杀死,因此为了正确清理well-behaved应用程序应该杀死子进程并完成通信:


【注意2】 pipe的有大小限制,Linux默认的pipe size是64KB。当大于64kb时,如果使用 Popen.wait() 方式等待程序结束获取返回值,会导致死锁,程序卡在 wait() 调用上。communicate将数据不是放在pipe中,而是放在内存中
所以,推荐使用communicate方式获得返回结果
【注意3】 输出输入小技巧:当参数传入不进去的时候,例如ip地址,可以将参数拼接在一起传入,例如(注意“ip”前面的加号+):

p=subprocess.Popen("ping -c 4 " + ip, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

3. 子进程常用方法
child.pid:返回子进程的pid

child.poll() :检查子进程状态

child.kill() :终止子进程

child.send_signal() :向子进程发送信号

child.terminate() :终止子进程

标签:函数,stdout,Python,Popen,subprocess,PIPE,call,subProcess
From: https://www.cnblogs.com/FireLife-Cheng/p/16791393.html

相关文章

  • Python中Try/Except/else/final语句
    python中的try/except/else/finally语句 与其他语言相同,在python中,try/except语句主要是用于处理程序正常执行过程中出现的一些异常情况,如语法错误(python作为脚本语言......
  • Python 小技巧:如何实现操作系统兼容性打包?
    有一个这样的问题:现要用setuptools把一个项目打包成whl文件,然后pipinstall在Windows/Linux两种操作系统上,但是该项目中有一些依赖库只有Windows上才有(例如pywin......
  • Python在计算内存时应该注意的问题?
    我之前的​​一篇文章​​​,带大家揭晓了Python在给内置对象分配内存时的5个奇怪而有趣的小秘密。文中使用了​​sys.getsizeof()​​来计算内存,但是用这个方法计算时,可......
  • Python 3.9 新特性:任意表达式可作为装饰器!
    一个月前(2月20日),一则新的PEP没有受到任何阻碍就被官方采纳了,这么快的速度,似乎并不多见。然而,更为高效率的是,仅在半个月内,它的实现就被合入了代码仓。也就是说,我们最快有望......
  • Python 的十万个为什么?
    随着Python在近些年的火爆,网上出现了很多这个方向的公众号和博客,文章也层出不穷。受到此风气的影响,我也把自己“培养”成了一名技术博主,写作近两年来,陆陆续续写过不少的系......
  • Python 3.9 性能优化:更快的 list()、dict() 和 range() 等内置类型
    Python的3.9.0版本正在开发中,计划在2020-10-05发布final版本。官方在​​changelog​​中披露了很多细节,其中有一项“vectorcall”特性是最容易被接受的,本文打算带......
  • Python 如何移除旧的版本特性,如何迎接新的特性?
    2020年4月20日,Python2的最后一个版本2.7.18发布了,这意味着Python2是真正的EOL(endoflife)了,一个时代终于落幕了。Python2.0版本是在2000年发布的,至今正好......
  • Python 为什么没有 main 函数?为什么我不推荐写 main 函数?
    毫无疑问Python中没有所谓的main入口函数,但是网上经常看到一些文章提“Python的main函数”、“建议写main函数”……有些人是知情的,他的意图可能是模仿那些正宗的......
  • Python 为什么不用分号作终止符?
    一般而言,编程语言中使用分号“;”来实现两种目的:作为语句分隔符:使用分号来分隔语句(statement),这样就能在一行代码中书写多条语句(一行多句)作为语句终止符:使用分号来终止语句,这......
  • Python小技巧:如何批量更新已安装的库?
    众所周知,升级某个库(假设为xxx),可以用​​pipinstall--upgradexxx​​​命令,或者简写成​​pipinstall-Uxxx​​。如果有多个库,可以依次写在xxx后面,以空格间隔。那......