python - presto - временные метки и десятичное число (38,18) возвращаются как строки? - PullRequest
0 голосов
/ 02 июля 2019

Почему типы данных prestatime / decimal (38,18) возвращают строку (заключенную в u '') вместо python datetime / numeric типов?

presto jdbc:

selecttypeof (col1), typeof (col2), typeof (col3), typeof (col4), typeof (col5), typeof (col6) из hive.xy

результат равен

метка времени метка времени bigintдесятичный (38,18) варчар варчар

desc hive.x.y
#result is
for_dt  timestamp   NO  NO  NO  NO  1
for_d   timestamp   NO  NO  NO  NO  2
for_h   bigint  NO  NO  NO  NO  3
value   decimal(38,18)  NO  NO  NO  NO  4
metric  varchar(2147483647) NO  NO  NO  NO  5
lat_lon varchar(2147483647) NO  NO  NO  NO  6

attempt 1
#python
from sqlalchemy.engine import create_engine
engine = create_engine('presto://u:p@host:port',connect_args={'protocol': 'https', 'requests_kwargs': {'verify': 'mypem'}})
result = engine.execute('select * from hive.x.y limit 1')
print(result.fetchall())
#result is
[(u'2010-02-18 03:00:00.000', u'2010-02-18 00:00:00.000', 3, u'-0.191912651062011660', u'hey', u'there')]

attempt 2
#python
from pyhive import presto
import requests
from requests.auth import HTTPBasicAuth

req_kw = {
'verify': 'mypem',
'auth': HTTPBasicAuth('u', 'p')
}

cursor = presto.connect(
host='host',
port=port,
protocol='https',
username='u',
requests_kwargs=req_kw,
).cursor()

query = '''select * from x.y limit 1'''
cursor.execute(query)
print cursor.fetchall()
#result is
[(u'2010-02-18 03:00:00.000', u'2010-02-18 00:00:00.000', 3, u'-0.191912651062011660', u'hey', u'there')]

1 Ответ

3 голосов
/ 07 июля 2019

Выходные данные, которые вы получаете по вашему SQL-запросу, поступают из базы данных в этом формате.

У вас есть два варианта

  1. Составьте карту данных самостоятельно (напишите собственный ORM)
  2. Научитесь пользоваться ORM

Вариант 1

Примечание. Я только что жестко закодировал ваш результат запроса для тестирования.

from sqlalchemy.engine import create_engine
from datetime import datetime
from decimal import Decimal

# 2010-02-18 03:00:00.000
dateTimeFormat = "%Y-%m-%d %H:%M:%S.%f"

class hivexy:
    def __init__(self, for_dt, for_d, for_h, value, metric, lat_lon):
        self.for_dt = for_dt
        self.for_d = for_d
        self.for_h = for_h
        self.value = value
        self.metric = metric
        self.lat_lon = lat_lon

    # Pretty Printing on print(hivexy)
    def __str__(self):
        baseString =  ("for_dt: {}\n"
                       "for_d: {}\n"
                       "for_h: {}\n"
                       "value: {}\n"
                       "metric: {}\n"
                       "lat_lon: {}\n")
        return baseString.format(for_dt, for_d, for_h, value, metric, lat_lon)

#engine = create_engine('presto://u:p@host:port',connect_args={'protocol': 'https', 'requests_kwargs': {'verify': 'mypem'}})
#results = engine.execute("select * from 'hive.x.y' limit 1")
results = [(u'2010-02-18 03:00:00.000', u'2010-02-18 00:00:00.000', 3, u'-0.191912651062011660', u'hey', u'there')]

hiveObjects = []

for row in results:
    for_dt = datetime.strptime(row[0], dateTimeFormat)
    for_d = datetime.strptime(row[1], dateTimeFormat)
    for_h = row[2]
    value = Decimal(row[3])
    metric = row[4]
    lat_lon = row[5]

    hiveObjects.append(hivexy(for_dt, for_d, for_h, value, metric, lat_lon))

for hiveObject in hiveObjects:
    print(hiveObject)

Вариант 2 При этом используется отражение - он запрашивает метаданные базы данных для типов полей, поэтому вам не нужно делать все это в варианте 1.

from sqlalchemy import *
from sqlalchemy.engine import create_engine
from sqlalchemy.schema import *

engine = create_engine('presto://u:p@host:port',connect_args={'protocol': 'https', 'requests_kwargs': {'verify': 'mypem'}})

# Reflection - SQLAlchemy will get metadata from database including field types
hiveXYTable = Table('hive.x.y', MetaData(bind=engine), autoload=True)
s = select([hiveXYTable]).limit(1)
results = engine.execute(s)

for row in results:
    print(row)
...