文档章节

python中执行命令行的方法 (二)交互式

BookShu
 BookShu
发布于 2016/06/22 14:56
字数 741
阅读 556
收藏 4

概述

  在上一篇文章(http://blog.csdn.net/styshoo/article/details/48755905)中,我们了解了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 subprocess
import fcntl, os
import time

pipe = 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 subprocess
import fcntl, os
import time
import select

pipe = 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

© 著作权归作者所有

共有 人打赏支持
BookShu
粉丝 31
博文 117
码字总数 86781
作品 0
西安
高级程序员
私信 提问
《Python3.6官方文档》– 第二章 使用python解释器

2.1. 调用解释器 Python解释器一般安装在 目录下,将 目录加入到Unix Shell脚本的命令搜索目录下,这样便可以通过输入以下shell命令已启动它[1]: 既然解释器的存放目录是安装时可选的,那么...

Skysper
2018/01/12
0
0
python学习-ipython和pyenv

一、ipython ipython是一个python的交互式shell,比默认的python shell好用得多,支持变量自动补全,自动缩进,支持bash shell命令,内置了许多很有用的功能和函数。学习ipython将会让我们以...

羊草
2018/08/01
0
0
jupyter notebook的安装与使用

概要 jupyter notebook是一个python交互式编辑器,是一个运行在wen上的运行程序,允许创建和共享包含实时代码,方程,可视化和说明文档。(简明一点就是ipython的升级版) 主要用途 更多的用途...

徐代龙
2018/04/30
0
0
python交互式shell-ipython

  前言   在写Python的时候,有时候需要命令行来测试一段代码,这时候就会用到交互式的shell。直接输入python就可以进入默认的shell,但是都没有提示,用起来不是很爽。这时候就可以用上...

linux运维菜
2018/11/25
0
0
Using the Python Interpret 之 Invoking the Interp

一,启动(invoking)python解释器 python解释器通常情况下如果你的机器允许的话会安装在 /usr/local/bin/python 目录下,然后你需要把这个路径放置到系统的环境变量中并且确保它生效,然后你...

Koma
2015/02/28
0
6

没有更多内容

加载失败,请刷新页面

加载更多

gcc -lm -lpthread 一类的理解

C代码调用math.h中的函数有问题,如sqrt函数。会出现问题(点击看问题)。 原因是调用<math.h>中的函数,编译时需要链接对应的库 libm -lm命令是使编译的时候,链接数学库; -lptread 链接线...

shzwork
39分钟前
0
0
关于360插件化Replugin Activity动态修改父类的字节码操作

近期在接入360插件化方案Replugin时,发现出现崩溃情况。 大概崩溃内容如下: aused by: java.lang.ClassNotFoundException: Didn't find class "x.x.x.xActivity" on path: 我自己在插件代码......

Gemini-Lin
今天
1
0
mybatis缓存的装饰器模式

一般在开发生产中,对于新需求的实现,我们一般会有两种方式来处理,一种是直接修改已有组件的代码,另一种是使用继承方式。第一种显然会破坏已有组件的稳定性。第二种,会导致大量子类的出现...

算法之名
昨天
21
0
单元测试

右键方法 Go To --> Test,简便快速生成测试方法。 相关注解 @RunWith(SpringRunner.class) 表示要在测试环境中跑,底层实现是 jUnit测试工具。 @SpringBootTest 表示启动整个 Spring工程 @A...

imbiao
昨天
4
0
欧拉公式

欧拉公式表达式 欧拉公式的几何意 cosθ + j sinθ 是个复数,实数部分也就是实部为 cosθ ,虚数部分也就是虚部为 j sinθ ,对应复平面单位圆上的一个点。 根据欧拉公式和这个点可以用 复指...

sharelocked
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部