python subprocess 非阻塞_通过阅读python subprocess源码尝试实现非阻塞读取stdout以及非阻塞wait...

本文详细解析了Python的subprocess模块如何实现非阻塞读取子进程的stdout以及非阻塞wait。通过阅读源码,了解到当stdout设置为subprocess.PIPE时,subprocess内部会创建管道并传递给子进程,子进程的输出会被父进程通过file对象读取。同时,介绍了如何通过线程来避免阻塞,实时获取子进程的回显。此外,还讨论了非阻塞地确认进程结束状态的方法,指出poll()是非阻塞的,而wait()是阻塞的,两者都调用了os.waitpid(),但选项不同。
摘要由CSDN通过智能技术生成

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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值