• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

Python—subprocess 进程管理

Python admin 5年前 (2015-06-03) 1651次浏览 0个评论 扫描二维码

最近,我们老大要我写一个守护者程序,对服务器进程进行守护。如果服务器不幸挂掉了,守护者能即时的重启应用程序。上网 Google 了一下,发现 Python 有很几个模块都可以创建进程。最终我选择使用 subprocess 模块,因为在 Python 手册中有这样一段话:

This module intends to replace several other, older modules and functions, such as: os.system、os.spawn*、os.popen*、popen2.*、commands.*

subprocess 被用来替换一些老的模块和函数,如:os.system、os.spawn*、os.popen*、popen2.*、commands.*。可见,subprocess 是被推荐使用的模块。

下面是一个很简单的例子,创建一个新进程,执行 app1.exe,传入相当的参数,并打印出进程的返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
import subprocess
returnCode = subprocess.call('app1.exe -a -b -c -d')
print 'returncode:', returnCode
#----- 结果 --------
#Python is powerful
#app1.exe
#-a
#-b
#-c
#-d
returncode: 0

app1.exe 是一个非常简单的控制台程序,它只打印出传入的参数,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
    cout << "Python is powerful" << endl;
    for (int i = 0; i < argc; i++)
    {
        cout << argv[i] << endl;
    }
    return 0;
}

闲话少说,下面开始详细介绍 subprocess 模块。subprocess 模块中只定义了一个类: Popen。可以使用 Popen 来创建进程,并与进程进行复杂的交互。它的构造函数如下:

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 参数来指定可执行文件的路径。在 windows 操作系统上,Popen 通过调用 CreateProcess()来创建子进程,CreateProcess 接收一个字符串参数,如果 args 是序列类型,系统将会通过 list2cmdline()函数将序列类型转换为字符串。

参数 bufsize:指定缓冲。我到现在还不清楚这个参数的具体含义,望各个大牛指点。

参数 executable 用于指定可执行程序。一般情况下我们通过 args 参数来设置所要运行的程序。如果将参数 shell 设为 True,executable 将指定程序使用的 shell。在 windows 平台下,默认的 shell 由 COMSPEC 环境变量来指定。

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

参数 preexec_fn 只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用。

参数 Close_sfs:在 windows 平台下,如果 close_fds 被设置为 True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。我们不能将 close_fds 设置为 True 同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

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

参数 cwd 用于设置子进程的当前目录。

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

参数 Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows 下用’/r/n’表示换,而 Linux 下用’/n’。如果将此参数设置为 True,Python 统一把这些换行符当作’/n’来处理。

参数 startupinfo 与 createionflags 只在 windows 下用效,它们将被传递给底层的 CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。

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.stdin

如果在创建 Popen 对象是,参数 stdin 被设置为 PIPE,Popen.stdin 将返回一个文件对象用于策子进程发送指令。否则返回 None。

Popen.stdout

如果在创建 Popen 对象是,参数 stdout 被设置为 PIPE,Popen.stdout 将返回一个文件对象用于策子进程发送指令。否则返回 None。

Popen.stderr

如果在创建 Popen 对象是,参数 stdout 被设置为 PIPE,Popen.stdout 将返回一个文件对象用于策子进程发送指令。否则返回 None。

Popen.pid

获取子进程的进程 ID。

Popen.returncode

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

下面是一个非常简单的例子,来演示 supprocess 模块如何与一个控件台应用程序进行交互。

1
2
3
4
5
6
7
8
9
10
11
12
13
import subprocess
p = subprocess.Popen("app2.exe", stdin = subprocess.PIPE, /
    stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False)
p.stdin.write('3/n')
p.stdin.write('4/n')
print p.stdout.read()
#---- 结果 ----
input x:
input y:
3 + 4 = 7

app2.exe 也是一个非常简单的控制台程序,它从界面上接收两个数值,执行加操作,并将结果打印到控制台上。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
int main(int argc, const char *artv[])
{
    int x, y;
    cout << "input x: " << endl;
    cin >> x;
    cout << "input y: " << endl;
    cin >> y;
    cout << x << " + " << y << " = " << x + y << endl;
    return 0;
}

supprocess 模块提供了一些函数,方便我们用于创建进程。

subprocess.call(*popenargs, **kwargs)

运行命令。该函数将一直等待到子进程运行结束,并返回进程的 returncode。文章一开始的例子就演示了 call 函数。如果子进程不需要进行交互,就可以使用该函数来创建。

subprocess.check_call(*popenargs, **kwargs)

与 subprocess.call(*popenargs, **kwargs)功能一样,只是如果子进程返回的 returncode 不为 0 的话,将触发 CalledProcessError 异常。在异常对象中,包括进程的 returncode 信息。

subprocess 模块的内容就这么多。在 Python 手册中,还介绍了如何使用 subprocess 来替换一些老的模块,老的函数的例子。赶兴趣的朋友可以看一下。

参考文档:

subprocess — Subprocess management

PyMoTW:subprocess

 

转自:http://python.jobbole.com/81517/


Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Python—subprocess 进程管理
喜欢 (0)
admin
关于作者:
互联网行业码农一枚/业余铲屎官/数码影音爱好者/二次元

您必须 登录 才能发表评论!