公司有埋点业务需要,所以需要用到athena数据库,但是苦于这玩意儿在网上能查到的太少
偶然间看到boto3可以连接athena数据库,然后自己稍微改造了下,能够顺利从数据库查出数据了
下面贴码
from boto3 import client
from time import sleep
from botocore.client import Config
from jsonpath import jsonpath
class Athena:
def __init__(self, region_name, aws_access_key_id, aws_secret_access_key, location):
config = Config(connect_timeout=30, read_timeout=30, retries={'max_attempts': 10})
self.clients = client('athena', region_name=region_name, aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key, config=config)
self.location = location
def getkey(self, data, keyword):
return jsonpath(data, f"$..{keyword}")
def getdata(self, sql):
response = self.clients.start_query_execution(
QueryString=sql,
ResultConfiguration={'OutputLocation': self.location}) # 发送sql语句
result = None
sleep(1)
for i in range(60): # 等待查询结果,等待结果超时的话就直接跳出
try:
result = self.clients.get_query_results(QueryExecutionId=response['QueryExecutionId']) # 查询结果
except:
sleep(1)
else:
break
results = self.getkey(result, 'Data') # 最终数据
if not results:
raise TimeoutError('Read Timeout')
keys=list(map(lambda x: list(x.values())[0] if list(x.values()) != [] else '', results[0])) #取键值
keys.insert(0,'index') #插入索引字段
# for i in results[0:] if len(results) ==1 else results[0:]: #无数据长度为1
for i in results:
data_dict = {}
for index,key in enumerate(keys,start=0):
if index==0:
data_dict[key]=None #索引默认None
continue
data_dict[key]=list(map(lambda x: list(x.values())[0] if list(x.values()) != [] else '', i))[index-1]
yield data_dict #数据转换成想要的格式
由于数据库在国外,所以发出查询后需要等到返回结果,本来在来连接配置中已经设置了超时,但是这里等待查询结果的时候会一直等待(网络超时),所以设置了查询循环,循环查结果,如果超出设置的次数就直接跳出不等了,然后最终查出的数据也很乱,不是pymysql、sqlalchemy那样的数据格式,所以最后把每一条的数据都转换了一次