Python Subprocess

在平时python的使用过程中,难免会遇到调用服务器命令的时候。直接调用普通的命令基本上都没有什么问题,令人比较麻烦的是带有控制台的命令,例如python、beeline、spark-shell。虽然向python、spark都有相关的脚本文件或者jar来避免直接使用控制台命令的调用,然后有些时候还是不免会用到控制台的方式,那么对于带有控制台的命令行应该如何实现呢?本文将使用subprocess,并以beeline为背景来实现使用python执行带有控制台的命令行命令。
首先看看参考代码,代码是以执行Hive的beeline命令行为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class beeline:
def __init__(self):
print "# 1 建立连接"
self.p = subprocess.Popen(['apache-hive-0.14.0-bin/bin/beeline'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
print >> self.p.stdin, '!connect jdbc:hive2://hdfs001:2181,hdfs002:2181,hdfs003:2181,hdfs004:2181,hdfs005:2181/;serviceDiscoveryMode=zookeeper userName password\n'
self.p.stdin.flush()
def submit(self, hql):
print "# 2 输入命令"
print >> self.p.stdin, hql
self.p.stdin.flush()
print "# 3 等待关闭"
print >> self.p.stdin, "!q"
self.p.wait()
def hadoop_get(self, from_, to_):
print "# 4 下载数据"
(status, output) = commands.getstatusoutput(" ".join(("hadoop-2.6.0/bin/hadoop fs -text", from_+'*', '>', to_)))
print status, output
def queryDataByDate(start_date, end_date, local_path):
sql = """
create table database.table_%s_%s
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '-@-'
NULL DEFINED AS '...'
STORED AS TEXTFILE
AS
SELECT * FROM DB.TABLE_NAME;
"""
b = beeline()
s = sql % (start_date, end_date, start_date, end_date)
b.submit((sql % (start_date, end_date, start_date, end_date)))
fileName = 'feed_%s_%s' % (start_date, end_date)
b.hadoop_get(("HDFS_PATH/%s/" % (fileName)), ("LOCAL_PATH/%s" % fileName))
if __name__ == '__main__':
if len(sys.argv) < 2:
print "请输入要获取feed的开始日期和结束日志,如:20160105"
exit(0)
print "正在执行%s文件,来查询%s-%s之间的数据:" % (sys.argv[0], sys.argv[1], sys.argv[2])
queryDataByDate(sys.argv[1], sys.argv[2], "/data/")

该代码块的主要流程是,在初始化beeline对象时调用beeline命令,并进行连接(init方法中实现了全部的操作);然后是提交需要beeline执行的sql(submit方法中实现);最后是将sql执行的结果从HDFS中取到本地(hadoop_get方法中实现)。queryDataByData方法就是对beeline类中各个方法的一个集成调用。