# -*- coding: gbk -*-
import os
import sys
import io
import subprocess
import _winreg
try: # 解除30天试用限制,Version>2.9。小于此版是ASProtect加密
_winreg.DeleteKey(_winreg.HKEY_CURRENT_USER, r'Software\Withdata\OraCmd')
except:
pass
def exists_oracmd():
"""是否存在 oracmd.exe 文件并返回文件名
"""
oracmd_exe = 'oracmd.exe'
cur_path = os.path.dirname(__file__)
cmd_file = os.path.join(cur_path, oracmd_exe)
if os.path.exists(cmd_file):
return cmd_file
else:
raise RuntimeError('文件 {} 不存在!'.format(cmd_file))
class OraCmd(object):
def __init__(self, userid):
self.userid = userid # username/password@host:port:SID
if sys.version_info[0]==2:
self._st=subprocess.STARTUPINFO
self._st.dwFlags=subprocess.STARTF_USESHOWWINDOW
self._st.wShowWindow=subprocess.SW_HIDE
else:
self._st = subprocess.STARTUPINFO(dwFlags=subprocess.STARTF_USESHOWWINDOW,
wShowWindow=subprocess.SW_HIDE)
def __oracmd_unload(self, query, delimiter, filename=None):
userid_ = "userid={}".format(self.userid)
query_ = "query={}".format(query)
delimiter_ = "delimiter={}".format(delimiter)
run_oracmd = exists_oracmd()
args = [run_oracmd, userid_, "task=unload", query_, delimiter_, "quit=y", "prompt=n"]
if filename:
datafile_ = "datafile={}".format(filename)
args.append(datafile_)
pipe = subprocess.Popen(args, stdout = subprocess.PIPE, stdin = subprocess.PIPE,
stderr = subprocess.PIPE, startupinfo = self._st)
return pipe
def unload_file(self, query, delimiter, filename=None):
"""执行SQL语句,并将结果输出到文件中
"""
if not filename:
filename = tempfile.mktemp() # 临时文件名
pipe = self.__oracmd_unload(query, delimiter, filename)
pipe.wait()
#! 未连上orale或query语句错误,不会实际生成filename文件
if os.path.exists(filename):
return filename
else:
return None
def fetch(self, query, delimiter=':,', readone=False):
"""query[IN]: select * from ......
delimiter[IN]: (",", "|", "#", "TAB", "WHITESPACE")
RETURN:
[] 或 None: 未查询到结果
[[a1,b1,...], [a2,b2,...]...] 或 [a,b,...]: 所有项都是string, 其中返回的Null是''
"""
pipe = self.__oracmd_unload(query, delimiter)
sout = io.open(pipe.stdout.fileno(), 'rb', closefd=False)
lines = ''
while True:
buf = sout.read1(1024)
if len(buf) == 0: break
lines += buf
if readone:
if '\r\n' in lines: break
# SQL执行成功:---------------------------------------------------------
# 1:有数据
# ver<=2.1
# A1,B1,C1\r\nA2,B2,C2\r\n...Am,Bm,Cm\r\n
# 尾部是\r\n,是一个空行,分解返回后会多一个['']
# ver>=2.2 remove the blank line at the end of the unload file.
# A1,B1,C1\r\nA2,B2,C2\r\n...Am,Bm,CmUnload succeeded. X records.\r\n0 h 0 m 0 s\r\n
# 尾部是Unload succeeded. X records.\r\n0 h 0 m 0 s\r\n
# 2:无数据
# ver<=2.1 ''
# ver>=2.2 Unload succeeded. 0 records.\r\n0 h 0 m 0 s\r\n
# 取值:不论版本也不论有无数据,[:-2]消除最后的\r\n,
# 然后split('Unload succeeded.')[0]
# SQL执行失败:---------------------------------------------------------
# ver<=2.1,返回的是''
# ver>=2.2, 错误提示\n\r\nUnload failed. \r\n0 h 0 m 0 s\r\n
## print repr(lines)
lines = lines[:-2].split('Unload succeeded.')[0]
if lines=='' or 'Unload failed.' in lines:
row = None if readone else []
else:
rows = lines.split('\r\n')
row = [r.split(delimiter) for r in rows]
row = row[0] if readone else row
return row
def fetchone(self, query, delimiter=':,'):
row = self.fetch(query, delimiter=':,', readone=True)
return row
if __name__ == '__main__':
userid = "nhzx/[email protected]:1521:rmis"
query_day = "SELECT rq, lm, rz FROM V_NHZX "\
" WHERE RQ >= TO_DATE('{}','yyyy-mm-dd') order by rq desc"
query = query_day.format('2021-08-01')
rmis = OraCmd(userid)
rmis.unload_file(query, ':,', r'z:\test.txt')
row = rmis.fetchone(query)
if row:
print row, '\n---------------'
row = rmis.fetch(query)
for i in row:
print i