写python程序的时候需要用到调用外部命令的模块,看了一下,还真不少,头疼,用着不顺手。根据官网推荐,我根据官网的subprocess模块定制了一个自己的shell,同时借鉴了github上面的shellpy模块,而且我觉得go语言的go-sh确实令人喜欢,所以我觉得基于流操作将会改变我们的很多工作。

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3.  
  4. import shlex
  5. from subprocess import Popen
  6. from subprocess import PIPE
  7.  
  8. def py_ver():
  9. '''
  10. 判断python的版本
  11. '''
  12. import sys
  13. return sys.version_info[0]
  14.  
  15. if py_ver() == 2:
  16. builtin_str = str
  17. bytes = str
  18. str = unicode
  19. basestring = basestring
  20. numeric_types = (int, long, float)
  21.  
  22. elif py_ver() == 3:
  23. builtin_str = str
  24. str = str
  25. bytes = bytes
  26. basestring = (str, bytes)
  27. numeric_types = (int, float)
  28. else:
  29. raise ValueError(u'python 版本不正确')
  30.  
  31. def parse_shell_token(t):
  32. import os
  33. # handle '~'
  34. t = os.path.expanduser(t)
  35. # handle env var
  36. t = os.path.expandvars(t)
  37. return t
  38.  
  39. def pipe_to_tmp(data):
  40. '''
  41. 把管道或者内存中的数据缓存到临时文件
  42. '''
  43. if isinstance(data, (unicode, str)):
  44. data = data.encode('utf-8')
  45.  
  46. import tempfile
  47. stdin_tmp = tempfile.SpooledTemporaryFile()
  48. stdin_tmp.write(data)
  49. stdin_tmp.seek(0)
  50. return stdin_tmp
  51.  
  52. class Shell(object):
  53.  
  54. def __init__(self, cmd_str, input_pipe=None):
  55. self.cmd_str = cmd_str
  56. self.popen = None
  57. self.input_pipe = input_pipe
  58. self.std = {'out': None, 'err': None}
  59.  
  60. def __getPopen(self):
  61. if self.popen is None:
  62. self.popen = Popen(
  63. map(parse_shell_token, shlex.split(self.cmd_str, posix=False)),
  64. stdin=self.input_pipe, stdout=PIPE, stderr=PIPE)
  65. return self.popen
  66.  
  67. def pipe(self, cmd_str):
  68. input_pipe = None
  69. pp = self.__getPopen()
  70. if pp.stdout.closed:
  71. # 如果命令已经执行,那么就把标准输出的结果保存到临时文件
  72. input_pipe = pipe_to_tmp(self.std['out'])
  73. else:
  74. input_pipe = pp.stdout
  75. # print input_pipe.read()
  76. # pp.stdout.close() # allow pp to receive SIGPIPE?
  77. return Shell(cmd_str, input_pipe=input_pipe)
  78.  
  79. def __communicate(self):
  80. pp = self.__getPopen()
  81. if pp.returncode is None:
  82. self.std['out'], self.std['err'] = pp.communicate()
  83.  
  84. def run(self):
  85. if self.std['out'] is None:
  86. self.__communicate()
  87. print self.std['out']
  88.  
  89. def stdout(self):
  90. if self.std['out'] is None:
  91. self.__communicate()
  92. return self.std['out']
  93.  
  94. def stderr(self):
  95. if self.std['err'] is None:
  96. self.__communicate()
  97. return self.std['err']
  98.  
  99. cmd = Shell
  100. if __name__ == '__main__':
  101.  
  102. # cmd('ls -l').run()
  103. # cmd('ls -l').pipe('grep Shell.py').run()
  104. # cmd('cat').pipe('> hello;cat hello').run()
  105.  
  106. # cmd('ls ~').run()
  107. cmd('echo dddd').run()
  108.  
  109. 下面这个是改良版本,参考了pythonbash类库的实现,仅用于学习
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from subprocess import Popen
  4. from subprocess import PIPE
  5. import shlex
  6.  
  7. def py_ver():
  8. '''
  9. 得到python的版本
  10. '''
  11. import sys
  12. return sys.version_info[0]
  13. _ver = py_ver()
  14.  
  15. if _ver == 2:
  16. builtin_str = str
  17. bytes = str
  18. str = unicode
  19. basestring = basestring
  20. numeric_types = (int, long, float)
  21.  
  22. elif _ver == 3:
  23. builtin_str = str
  24. str = str
  25. bytes = bytes
  26. basestring = (str, bytes)
  27. numeric_types = (int, float)
  28. else:
  29. raise ValueError(u'python 版本不正确')
  30. del _ver
  31.  
  32. #解析字符串中的环境变量
  33. def parse_shell_token(t):
  34. import os
  35. #将~等用用户的家目录进行替换
  36. t = os.path.expanduser(t)
  37. #path中可以使用环境变量,'$PATH'...
  38. t = os.path.expandvars(t)
  39. return t
  40.  
  41. class cmd(object):
  42. def __init__(self, *args, **kwargs):
  43. self.stdout = None
  44. self.cmd(*args, **kwargs)
  45. def cmd(self, cmd, env=None, stdout=PIPE):
  46. p = Popen(parse_shell_token(cmd), shell=True,
  47. stdout=stdout, stdin=PIPE, stderr=PIPE, env=env)
  48. self.stdout, self.stderr = p.communicate(input=self.stdout)
  49. self.code = p.returncode
  50. return self
  51. def __repr__(self):
  52. return self.value()
  53.  
  54. def __unicode__(self):
  55. return self.value()
  56.  
  57. def __str__(self):
  58. return self.value()
  59.  
  60. def __nonzero__(self):
  61. return self.__bool__()
  62.  
  63. def __bool__(self):
  64. return bool(self.value())
  65.  
  66. def value(self):
  67. if not self.stdout:
  68. return ''
  69. return self.stdout.strip()
  70.  
  71. if __name__ == '__main__':
  72. #print cmd('ls -l')
  73. print cmd("ls . | grep 'pyc'")
  74. #print cmd("konsole --hold -e 'konsole --help'")
  75. #print cmd('scrapy list')
  76. print cmd('ls $HOME')
  77. #print cmd('ls ~')

python执行外部程序模块pyshell的更多相关文章

  1. python执行外部命令并获取输出

    使用subprocess库 import subprocess out_bytes = subprocess.check_output(['netstat','-a']) out_bytes = su ...

  2. python 利用python的subprocess模块执行外部命令,获取返回值

    有时执行dos命令需要保存返回值 需要导入库subprocess import subprocess p = subprocess.Popen('ping www.baidu.com', shell= ...

  3. Python入门笔记(26):Python执行环境

    一.python特定的执行环境 在当前脚本继续进行 创建和管理子进程 执行外部命令或程序 执行需要输入的命令 通过网络来调用命令 执行命令来创建需要处理的输出 动态生成Python语句 导入Pytho ...

  4. Python调用外部系统命令

    利用Python调用外部系统命令的方法可以提高编码效率.调用外部系统命令完成后可以通过获取命令执行返回结果码.执行的输出结果进行进一步的处理.本文主要描述Python常见的调用外部系统命令的方法,包括 ...

  5. Python学习(25):Python执行环境

    转自 http://www.cnblogs.com/BeginMan/p/3191856.html 一.python特定的执行环境 在当前脚本继续进行 创建和管理子进程 执行外部命令或程序 执行需要输 ...

  6. 利用Python读取外部数据文件

      不论是数据分析,数据可视化,还是数据挖掘,一切的一切全都是以数据作为最基础的元素.利用Python进行数据分析,同样最重要的一步就是如何将数据导入到Python中,然后才可以实现后面的数据分析.数 ...

  7. python 执行环境

    一些函数 执行其它非python程序 1 一些函数 callable callable()是一个布尔函数,确定一个对象是否可以通过函数操作符(())来调用.如果函数可调用便返回True,否则便是Fal ...

  8. Python执行系统命令的四种方法

    一.os.system方法 在子终端运行系统命令,可以获取命令执行后的返回信息以及执行返回的状态.执行后返回两行结果,第一行是结果, 第二行是执行状态信息,如果命令成功执行,这条语句返回0,否则返回1 ...

  9. python执行环境

    转自 http://www.cnblogs.com/BeginMan/p/3191856.html 一.python特定的执行环境 在当前脚本继续进行 创建和管理子进程 执行外部命令或程序 执行需要输 ...

随机推荐

  1. 关于《Cocos2d-x建工程时避免copy文件夹和库》的更新

    在前几篇博文中大概了解了Cocos2d-x引擎的基本结构后打算开始实际操作,便在网上转载了一篇关于VS新建Cocos2d-x项目的文章.今天实际操作的时候发现博主使用的引擎版本和我的不一致(<C ...

  2. regular expression 基本语法

    正则检测网址: http://regexpal.isbadguy.com/   (不包含界定符)   或  http://tool.chinaz.com/regex unicode转换工具 : htt ...

  3. Redis 入门之编译安装

    Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMware主 ...

  4. google浏览器翻译失败解决方案

    用记事本打开 C:\Windows\System32\drivers\etc下hosts文件 在文件末尾加入如下两行 203.208.46.145 translate.google.com 203.2 ...

  5. [Errno 11004] getaddrinfo failed

    该程序是在用python发送邮件的时候出现的 出现这个错误的时候,证明连不上你的帐号,或者登录不上服务器~超时连接 检查下自己的帐号或者服务器的编写有没有正确

  6. Java--static interface

    http://stackoverflow.com/questions/8374646/what-is-a-static-interface-in-java http://stackoverflow.c ...

  7. 认识元数据和IL(中)<第四篇>

    书接上回[第二十四回:认识元数据和IL(上)],我们对PE文件.程序集.托管模块,这些概念与元数据.IL的关系进行了必要的铺垫,同时顺便熟悉了以ILDASM工具进行反编译的基本方法认知,下面是时候来了 ...

  8. hdu 3874 Necklace(bit树+事先对查询区间右端点排序)

    Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful v ...

  9. linux多线程socket编程一些心得

    http://hi.baidu.com/netpet/blog/item/2cc79216d9012b54f2de32b9.html 前段时间将新的web模型办到linux上来,用epoll代替了IO ...

  10. sendto() 向广播地址发包返回errno 13, Permission denied错误

    http://blog.csdn.net/guanghua2_0beta/article/details/52483916 sendto() 向广播地址发包返回errno 13, Permission ...