暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

手工打造Python的Oracle sql执行工具

原创 陈坤 云和恩墨 2022-02-26
1778

使用python开发执行oracle sql的自动化执行脚本,一般可以使用oracle官方提供的python包:cx_Oracle。但有些情况下,目标主机上如果没有安装此工具,就需要使用最原始的手段编写python和oracle数据库交互的工具。

这个工具时通过python中的subprocess模块实现的,subprocess时一个子进程管理类,它允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码,而这个模块的底层的进程创建与管理由Popen类处理。

可以把创建一个Popen对象理解为建立了一个子进程,然后可以给这个子进程传递执行命令或函数,并从中获得执行结果。


在python中使用subprocess模块,通过shell和oracle数据库进行交互,具体流程可以总结为以下几步:


1,直接用oracle用户执行脚本,或使用root执行脚本,在脚本中通过os.setuid函数,将当前执行的用户切换到oracle


2,获取ORACLE_HOME环境变量,很多环境并不会在.bash_profile中配置环境变量,所以执行sqlplus时需要提前声明。export ORACLE_SID=xxx


3,使用sqlplus 登录数据库,如果允许,可以使用sysdba 登录,并且使用参数-S,静默登录:sqlplus -S / as sysdba

cmd = 

'''export ORACLE_SID=xxx

sqlplus -S / as sysdba

'''


4,创建一个python subprocess模块中的Popen对象,将指定环境变量,sqlplus登录作为第一个参数传递进去:

如果只看定义的话,创建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)

但其实一般使用用不到这么多入参,下面就是一个只有第一个必填入参的简单例子,来自于官方文档,

>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!

在官方文档是这样解释Popen()的第一个参数args:

在Unix上,如果args是字符串,则该字符串将被解释为要执行的程序的名称或路径。

官方文档进一步解释道:

注意如果你想要向进程的 stdin 传输数据,你需要通过 stdin=PIPE 创建此 Popen 对象。类似的,要从结果元组获取任何非 None 值,你同样需要设置 stdout=PIPE 或者 stderr=PIPE。

所以我们需要通过stdin标准输入传递具体的执行sql,并从stdout标准输出中获取执行结果,在创建Popen对象时就必须使用 stdout=PIPE, stderr=PIPE, stdin=PIPE


官方文档还指出:

参数 shell (默认为 False)指定是否使用 shell 执行程序。如果 shell 为 True,更推荐将 args 作为字符串传递而非序列。


最终,在我们的工具中,应该这样创建一个Popen对象,将上一步拼接的cmd字符串传递进去即可,后面参数使用上面推荐的值:

p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE)

完成了第四步,就建立一个打开了sqlplus 的子进程。


5,将要执行的sql输入到建立好的子进程中

比如要执行“select owner,object_name,object_type from dba_objects where status='INVALID';"查找失效对象。需要使用communicate函数去执行,并接收标准输出和错误输出:

sql = "select owner,object_name,object_type from dba_objects where status='INVALID';"

stdout, stderr  = p.communicate(input=str.encode(sql))

sql的执行结果就会在stdout中了。

注意:sql在oracle中执行的报错内容也属于标准输出stdout,并不会在错误输出里。

communicate函数的功能是与进程交互:向stdin发送数据。然后从stdout读取数据,并等待进程终止。

最后会给整个Popen设置一个状态,如果是执行正常,状态为0,从p.returncode中可以获得这个值,如果是None则表示进程当前并未结束。


这样,一个简单的同步流程的python的oracle sql执行工具就完成了。下一步,可以针对特殊情况进行处理,还可以继续发掘Popen对象的功能,创建一套异步流程。








最后修改时间:2022-02-26 17:22:06
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论