文档章节

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

BookShu
 BookShu
发布于 2016/06/22 14:56
字数 741
阅读 537
收藏 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

没有更多内容

加载失败,请刷新页面

加载更多

搜索引擎(Solr-索引详解)

时间字段类型特别说明 Solr中提供的时间字段类型( DatePointField, DateRangeField,废除的TrieDateField )是以时间毫秒数来存储时间的。 要求字段值以ISO-8601标准格式来表示时间:YYYY-MM...

这很耳东先生
23分钟前
0
0
Java成神之路

1、基础篇 01、面向对象 → 什么是面向对象 面向对象、面向过程 面向对象的三大基本特征和五大基本原则 → 平台无关性 Java 如何实现的平台无关 JVM 还支持哪些语言(Kotlin、Groovy、JRuby...

asdf08442a
53分钟前
2
0
dubbo源码分析-服务导出

简介 dubbo框架spring Schema扩展机制与Spring集成,在spring初始化时候加载dubbo的配置类。 dubbo服务导出的入口类是ServiceBean的onApplicationEvent方法 ServiceBean的继承关系如下 publ...

王桥修道院副院长
59分钟前
0
0
QQ音乐的动效歌词是如何实践的?

本文由云+社区发表 作者:QQ音乐技术团队 一、 背景 1. 现状 歌词浏览已经成为音乐app的标配,展示和动画效果也基本上大同小异,主要是单行的逐字染色的卡拉OK效果和多行的滚动效果。当然,我...

腾讯云加社区
59分钟前
4
0
idea里配置springboot项目打热部署

首先添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional></dependency> 然后添......

shatian
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部