最近需要在python服务端实现读取hive数据的功能,本以为会比较容易实现,结果因为需要同时支持在Linux(部署)和windowns(开发)上运行,稍微费了一番功夫查询和尝试。
在网上稍微搜索了一下,支持python连接到hive的第三方包有pyhive、pshs2、impala。
GitHub参考链接
pyhive => https://github.com/dropbox/PyHive
pyhs2 => https://github.com/BradRuderman/pyhs2
impala => https://github.com/cloudera/impyla
但是pyhs2的作者已经停止维护了,所以可以使用另外两种方式。
pyhive的文档很详细,要注意的有两点:
官方提供四种连接方式,分别是DB-API
,DB-API (asynchronous)
,SQLAlchemy
,Passing session configuration
。文档很详细。
from pyhive import presto # or import hive
cursor = presto.connect(host='192.168.10.10',port=10000).cursor()
cursor.execute('SELECT * FROM user LIMIT 10')
data = cursor.fetchall()
print(data)
最终选择了impala,对Windowns和Linux的支持都很好。
安装包:
pip install bit_array
pip install thrift
pip install thriftpy
pip install pure_sasl
pip install --no-deps thrift-sasl==0.2.1
pip install impyla
这里安装thrift-sasl要使用无依赖模式,否则会顺便安装sasl,在使用的时候sasl会导致报错。
安装好之后,使用如下代码:
from impala.dbapi import connect
import pandas as pd
conn = connect(host='192.168.10.10', port=10000, user=None, password=None, database='default', auth_mechanism="PLAIN")
cur = conn.cursor()
cur.execute("desc user")
d = cur.fetchall()
cols = []
for i in d:
cols.append(i[0])
cur.execute('select * from user')
data = cur.fetchall()
df = pd.DataFrame(data, columns=cols)
print(df)
即可直接把hive中的数据导入为DataFrame。
================
以下报错解决方案参考自 aitolearn.com 且通过验证
impyla (0.14.0) ERROR - ‘TSocket’ object has no attribute ‘isOpen’
这个问题的原因是thrift-sasl
版本过高导致的,将其换成0.2.1
的版本即可
pip install thrift-sasl==0.2.1
thriftpy2.protocol.exc.TProtocolException: TProtocolException(type=4)
这是由于auth_mechanism
设置的问题导致的,加上或将其改为auth_mechanism="PLAIN"
即可
TypeError: can’t concat str to bytes
修改 python site-package中的thrift-sasl包init.py
文件,在第94行之前加上以下语句即可:
if (type(body) is str):
body = body.encode()
thrift.transport.TTransport.TTransportException: Could not start SASL: b’Error in sasl_client_start (-4) SASL(-4): no mechanism available: Unable to find a callback: 2’
这是Windows下采用pyhive连接方式提出的错误,正如前言所述,可能需要修改对应的配置文件,也可能sasl根本就不支持Windows,建议改用impyla形式连接
thriftpy.parser.exc.ThriftParserError: ThriftPy does not support generating module with path in protocol ‘c’
修改thriftpy
包下\parser\parser.py
中第488行代码
将
if url_scheme == '':
修改为下面的代码
if len(url_scheme) <=1: