博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python中执行命令行的方法 (二)交互式
阅读量:6368 次
发布时间:2019-06-23

本文共 1994 字,大约阅读时间需要 6 分钟。

hot3.png

概述

  在上一篇文章()中,我们了解了python执行命令行的几种方法。然而,之前介绍的方法中,却无法进行交互式地调用,即命令只能一次执行,执行之后就结束了。如果我们需要交互式地调用,如调用一个命令,在此过程中间断性的输入输出,那么之前的方法就不适合使用了。想要达到这个目的,就必须使用管道了。

  在python中,有两种使用管道的方法,一种是前文中提到的popen,不过该函数已经在2.6版本中被建议弃用了,取代它的就是马上会提到的第二种方法:subprocess模块。

使用

  subprocess模块是python2.4新加入的模块,而加入该模块的目的,正是为了替代上文中提到的那些模块或函数:os.system、os.spawn、os.popen、popen2和commands等。subprocess模块使用管道是通过该模块的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)

  创建该类时就生成了一个管道,要通过管道交互,可再直接通过该管道的stdout和stdin对象来实现。然而,默认情况下,subprocess只在子进程结束时才会读取一次标准输出。因此,我们需要将标准输出改为非阻塞的模式。这里,我们以在“sh”下执行ls命令来模拟(真实情况下肯定不会这么简单啦)。

import subprocessimport fcntl, osimport timepipe = subprocess.Popen("sh", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)flags = fcntl.fcntl(pipe.stdout, fcntl.F_GETFL)fcntl.fcntl(pipe.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)pipe.stdin.write("ls \n")pipe.stdin.flush()time.sleep(2)out = pipe.stdout.read()print out

进阶

  在上面的代码中,在从输出读数据之前,有一个休眠两秒的操作。之所以这样,是因为这里所有的操作都是针对子进程的,在主线程中并不会等待。如果没有这个休眠操作,那么就会在执行输入的ls操作同时,就直接尝试从输出读取了,这时,很有可能会出现读取异常。试想下,如果向输入写的是“sleep 10; ls”这样的操作,那么就百分百会出现读取异常了。

  然而,这种休眠操作并不友好,因为直接写入休眠时间,而实际情况中,我们并不能确认休眠的时间长短。有什么办法可以解决么?当然有,就是类UNIX系统的epoll操作。这里我直接写入代码,有兴趣的同学可以参考下reference来了解详细的情况。

import subprocessimport fcntl, osimport timeimport selectpipe = subprocess.Popen("sh", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)flags = fcntl.fcntl(pipe.stdout, fcntl.F_GETFL)fcntl.fcntl(pipe.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)pipe.stdin.write("sleep 10; ls \n")pipe.stdin.flush()poll = select.epoll()poll.register(pipe.stdout.fileno())epoll_list = poll.poll()for fd, events in epoll_list:    if fd == pipe.stdout.fileno() and select.EPOLLIN & events:        out = pipe.stdout.read()        print out

转载于:https://my.oschina.net/styshoo/blog/699276

你可能感兴趣的文章
免费的多平台使用的桌面日程安排软件?
查看>>
Java 实现阿里云直播
查看>>
javascript中的内存管理和垃圾回收
查看>>
Hbase java 常见操作
查看>>
Python网络编程——协程
查看>>
laravel中短信发送验证码的实现方法
查看>>
10月25日云栖精选夜读 | 机器学习高质量数据集大合辑
查看>>
fastjson实例
查看>>
服务器架构
查看>>
【Android学习】Android studio 使用AIDL
查看>>
【20160924】GOCVHelper MFC增强算法(2)
查看>>
阿里云安全肖力:云的六大安全基因助力企业构建智能化安全体系
查看>>
豆瓣阅读报告生成器
查看>>
building with Gulp
查看>>
五年 Clojure 使用者浅谈 Clojure 语言的设计
查看>>
Tomcat 中的 JDBC Pool
查看>>
有趣的代码攻防战
查看>>
网络通信框架 HP-Socket v5.5.1,支持可靠 UDP
查看>>
mysql集群搭建部署
查看>>
CSS-右下角的边框半径 | border-bottom-right-radius
查看>>