python通过subprocess模块也能实现类似功能。
因为python拥有丰富的数据接口,简洁的语法,让python在进行类似的工作时比shell更容易维护。
subprocess模块是在python2.4的时候引入。详细信息查看PEP 324
介绍
subprocess主要有以下几个函数:
call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
check_output(args, *, input=None, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None)
这些函数底层都是使用Popen 类,该类拥有的方法和属性有有:poll()
wait(timeout=None) #timeout python3.3开始引入
communicate(input=None, timeout=None)
send_signal(signal)
terminate()
kill()
args
stdin
stdout
stderr
pid
returncode
例子
当前例子环境为:python3.4+windows10。
主要为了实现:python调用mysql,向mysql传递命令,获取mysql执行之后的结果。
方法1:
通过变量传递和保存输入输出,使用Popen
def test1():
child1=subprocess.Popen(['mysql','-udemo','-pdemo'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
(stdout,stderr)=child1.communicate(input=b'use demo;\n show tables;\nexit\n')
print(stdout.decode())
方法1还有一种写法,直接向stdin写入命令,直接从stdout读出结果:def test11():
child1=subprocess.Popen(['mysql','-udemo','-pdemo'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
child1.stdin.write(b'use demo;\n show tables;\nexit\n');
child1.stdin.close()
print(child1.stdout.read().decode())
child1.stdout.close()
方法2:
通过变量传递输入,将输出保存到文件中,使用Popen
def test2():
outfile=r'result.txt'
child1=subprocess.Popen(['mysql','-udemo','-pdemo','-s'],stdin=subprocess.PIPE,stdout=open(outfile,'wb'))
child1.communicate(input=b'use demo;\n show tables;\nexit\n')
if child1.returncode==0:
with open(outfile) as f:
print(f.read())
方法3:
通过文件传递输入,将输出保存到文件中,使用Popen
def test3():
infile=r'sql.txt'
outfile=r'result.txt'
child1=subprocess.Popen(['mysql','-udemo','-pdemo','-s','-h172.16.1.141'],stdin=open(infile,'rb'),stdout=open(outfile,'wb'))
print('input:')
with open(infile) as f:
print(f.read())
print('output:')
with open(outfile) as f:
print(f.read())
对于方法3,还有另外一种写法,使用call:def test31():
infile=r'sql.txt'
outfile=r'result.txt'
result_code=subprocess.call(['mysql','-udemo','-pdemo','-s','-h172.16.1.141'],stdin=open(infile,'rb'),stdout=open(outfile,'wb'))
print('input:')
with open(infile) as f:
print(f.read())
if result_code==0:
print('output:')
with open(outfile) as f:
print(f.read())
一些参数说明:
Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())
中的stdin,stdout,stderr需要是PIPE, DEVNULL, None或者是file descriptor 。如果传入的参数是PIPE,那么Popen会自己建立一个pipe,可以把这个pipe当做一个文件,stdin可以往里面写(写完命令之后,注意close),stdout可以从里面读。参考test11()
如果stdin是file descriptor ,需要文件中有准备好的内容,因为进程在执行的时候,会直接从这个文件中读取数据。参考test3()或test31()
Popen.communicate(input=None, timeout=None)
中的input需要是None,或者bytes(如果universal_newlines =True,可以是string),这个函数只能调用一次,调用之后会一直等待,直到进程停止。总结
如果是一些简单的调用,执行使用call、check_call、check_output就行了。
如果需要更精细的控制,使用Popen可以完成。如果是进程间的通信,使用PIPE,如果仅仅传入一些命令,使用文件或者communicate中的input既可。
以上是一个例子,真正和MySQL交互的时候可以使用其提供的客户端mysql-connector直接进行交互 。