Jupyter から Hive を使うのに PyHive + ipython-sql が便利だった。
PyHive
PyHive は Hive の Thrift クライアントを DB-API 2.0 (PEP 249) 準拠の API でラップするライブラリだ。DB-API は Python でデータベースにアクセスするための標準的なインターフェースで、Perl の DBI や Java の JDBC に相当する。
PyHive と pandas.read_sql があれば、とりあえず SQL の結果を pandas に読み込むことはできるようになる。
ipython-sql
世の中には「SQL を書くのは最初だけで、pandas に読み込んでからが本番」という仕事をしている人もいるんだろうけど、私の場合は SQL 上でいろいろすることのほうが多いので ipython-sql も使っている。
これがあると
pd.read_sql("select * from ...", conn)
ではなく
%% sql
select * from ...
というふうに、セルに直接 SQL が書けるようになる。
落とし穴: DB-API とプレースホルダ
Python の DB-API にはプレースホルダ構文があるので、ipython-sql でもそのことを意識する必要がある。
ipython-sql の README.rst には
Bind variables (bind parameters) can be used in the “named” (:x) style. The variable names used should be defined in the local namespace
と書かれているけど、この前半の :x
形式が使えるかは DB-API の実装に依存している。
PyHive の場合は pyformat という printf 風の形式にのみ対応している ので、結果として
%% sql
select * from developer where name like '%steve%'
なんてクエリを実行しようとすると
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-983b54b86e01> in <module>()
----> 1 get_ipython().magic(u"select * from developer where name like '%steve%'")
/Users/kazuyoshi/src/jupyter-work/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in magic(self, arg_s)
2156 magic_name, _, magic_arg_s = arg_s.partition(' ')
2157 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2158 return self.run_line_magic(magic_name, magic_arg_s)
2159
2160 #-------------------------------------------------------------------------
...
/Users/kazuyoshi/src/jupyter-work/lib/python2.7/site-packages/pyhive/hive.pyc in execute(self, operation, parameters, async)
227 sql = operation
228 else:
--> 229 sql = operation % _escaper.escape_args(parameters)
230
231 self._reset_state()
TypeError: not enough arguments for format string
というエラーになってしまう。'%%steve%%'
とエスケープする必要があり、ちょっと面倒くさい。