http://blog.chinaunix.net/uid-23504396-id-4661783.html
执行subprocess的时候,执行不是问题
最麻烦的是获取进程执行后的回显来确认是否正确执行,还不能阻塞
还要获取进程执行后的返回状态确认进程是否正确结束,也不能阻塞
分开解决这个问题
我们先解决第一个问题,获取回显
一般获取回显,代码都是如下写法
点击(此处)折叠或打开
sub_process = subprocess.Popen(command, stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE, shell = True)
为了搞清楚subprocess是怎么获取子进程stdout的,我们首先看看 subprocess.PIPE是什么
进入代码里可以看见subprocess.PIPE 直接是个int -1
再看看网上一般获取subprocess回显的代码
点击(此处)折叠或打开
lines = sub_process.stdout.readline()
subprocess.PIPE是-1,为什么Popen这个类的stdout变成了什么对象,可以用readline方法呢
打印type可以知道Popen对象的stdout的类型是file,我们看看subprocess里做了什么操作。
我们看看Popen的init方法(python 2.7.8)
stdout传入_get_handles函数准换出(p2cread, p2cwrite,c2pread, c2pwrite,errread, errwrite)
点击(此处)折叠或打开
(p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
p2cread, p2cwrite,c2pread, c2pwrite,errread, errwrite 传入_execute_child中,这个函数看名字就知道是真正的执行函数
点击(此处)折叠或打开
self._execute_child(args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
p2cread, p2cwrite,c2pread, c2pwrite,errread, errwrite传入执行函数后,stdout等通过fdopen函数转换问file对象
点击(此处)折叠或打开
if p2cwrite is not None:
self.stdin = os.fdopen(p2cwrite, ‘wb‘, bufsize)
if c2pread is not None:
if universal_newlines:
self.stdout = os.fdopen(c2pread, ‘rU‘, bufsize)
else:
self.stdout = os.fdopen(c2pread, ‘rb‘, bufsize)
if errread is not None:
if universal_newlines:
self.stderr = os.fdopen(errread, ‘rU‘, bufsize)
else:
self.stderr = os.fdopen(errread, ‘rb‘, bufsize)
我们先看看_get_handles方法,部分代码如下
点击(此处)折叠或打开
def _get_handles(self, stdin, stdout, stderr):
"""Construct and return tuple with IO objects:
p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
"""
p2cread, p2cwrite = None, None
c2pread, c2pwrite = None, None
errread, errwrite = None, None
if stdin is None:
pass
elif stdin == PIPE:
p2cread, p2cwrite = self.pipe_cloexec()
elif isinstance(stdin, int):
p2cread = stdin
else:
# Assuming file-like object
p2cread = stdin.fileno()
再跟踪进去看pipe_cloexec
点击(此处)折叠或打开
def pipe_cloexec(self):
"""Create a pipe with FDs set CLOEXEC."""
# Pipes‘ FDs are set CLOEXEC by default because we don‘t want them
# to be inherited by other subprocesses: the CLOEXEC flag is removed
# from the child is FDs by _dup2(), between fork() and exec().
# This is not atomic: we would