今回はちょっと長いので久々に目次を付けます。
Contents


psqlに代わる?モダンなPython製ターミナル

pgcliです。公式サイトのスクリーンショットを見れば、psqlが一気にかすんでしまいそう。前から気になっていましたが、先日セットアップしたpgAdmin4Windows用バイナリでPythonpippsycopg2がすぐ使える形だったので、pgcliのインストールを試したらあっさり成功。で少し使ってみました。実行環境はWindows7 x64、管理者権限ユーザです。


pipでインストール

先日使ったpgAdmin4 Beta1Windows版は ↓ こんなフォルダ構成。詳細は11日の記事(デスクトップアプリ)または12日の記事(ウェブアプリ)を見て下さい。このうちpgcliに必要なのはvenvフォルダだけ。
pgAdmin 4
  ┗ v1
   ┣ docs
   ┣ installer
   ┣ runtime
   ┣ venv(これだけ使う)
   ┃ ┣ DLLs
   ┃ ┣ Lib
   ┃ ┣ python27.dll
   ┃ ┗ python.exe
   ┗ web
     ┗ pgAdmin4.py


今回、venvを適当な所にコピーしてpgcliを入れました。ネットワークに接続してpip installするだけ。必要パッケージが自動取得されてあっさり成功。↓
r:\venv> python -m pip install pgcli

Collecting pgcli
  Downloading pgcli-0.20.1.tar.gz (46kB)
    100% |################################| 49kB 65kB/s
Collecting pgspecial>=1.1.0 (from pgcli)
  Downloading pgspecial-1.4.0.tar.gz
Collecting click>=4.1 (from pgcli)
  Downloading click-6.6.tar.gz (283kB)
    100% |################################| 286kB 70kB/s
Requirement already satisfied (use --upgrade to upgrade): Pygments>=2.0 in r:\venv\lib\site-packages (from pgcli) 
Collecting prompt-toolkit==0.46 (from pgcli)
  Downloading prompt_toolkit-0.46-py2-none-any.whl (168kB)
    100% |################################| 172kB 82kB/s
Collecting psycopg2>=2.5.4 (from pgcli)
  Downloading psycopg2-2.6.1-cp27-none-win32.whl (814kB)
    100% |################################| 815kB 175kB/s
Collecting sqlparse==0.1.16 (from pgcli)
  Downloading sqlparse-0.1.16.tar.gz (58kB)
    100% |################################| 61kB 93kB/s
Collecting configobj>=5.0.6 (from pgcli)
  Downloading configobj-5.0.6.tar.gz
Requirement already satisfied (use --upgrade to upgrade): six>=1.9.0 in r:\venv\lib\site-packages (from prompt-toolkit==0.46->pgcli)
Collecting wcwidth (from prompt-toolkit==0.46->pgcli)
  Downloading wcwidth-0.1.6-py2.py3-none-any.whl
Building wheels for collected packages: pgcli, pgspecial, click, sqlparse, configobj
  Running setup.py bdist_wheel for pgcli
(...)
Successfully built pgcli pgspecial click sqlparse configobj
Installing collected packages: click, sqlparse, pgspecial, wcwidth, prompt-toolk
it, psycopg2, configobj, pgcli
  Found existing installation: sqlparse 0.1.19
    Uninstalling sqlparse-0.1.19:
      Successfully uninstalled sqlparse-0.1.19
  Found existing installation: psycopg2 2.5.2
    Uninstalling psycopg2-2.5.2:
      Successfully uninstalled psycopg2-2.5.2
Successfully installed click-6.6 configobj-5.0.6 pgcli-0.20.1 pgspecial-1.4.0 prompt-toolkit-0.46 psycopg2-2.5.2 sqlparse-0.1.16 wcwidth-0.1.6 
You are using pip version 7.1.2, however version 8.1.2 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.


↓ 新しいフォルダvenv/Scriptsが作られ、その中にpgcliがあります。--helpオプションで起動できることを確認。パス設定は特に不要でした。
venv
 ┣ Dlls
 ┣ Lib
 ┗ Scripts(新しく出来た)
  ┣ pgcli.exe
  ┗ sqlformat
R:\venv\Scripts>pgcli --help
Usage: pgcli [OPTIONS] [DATABASE] [USERNAME]

Options:
  -h, --host TEXT     Host address of the postgres database.
  -p, --port INTEGER  Port number at which the postgres instance is
                      listening.
  -U, --user TEXT     User name to connect to the postgres database. 
  -W, --password      Force password prompt.
  -w, --no-password   Never prompt for password.
  -v, --version       Version of pgcli.
  -d, --dbname TEXT   database name to connect to.
  --pgclirc TEXT      Location of pgclirc file.
  --help              Show this message and exit.


フォルダを移すと使えなくなる…

無事インストールできたので、ポータブルに使えるかの確認でフォルダを移したら致命的な問題発生。全く動きません。↓
R:\moved\venv\Scripts>pgcli --help
Fatal error in launcher: Unable to create process using '"' 

R:\moved\venv\Scripts>pgcli -p 5952 -U postgres
Fatal error in launcher: Unable to create process using '"'


絶対パスがどこかで記憶されてるのかな~と思い、いったんpip uninstallし(これは成功)、再インストールを試みたら ↓psycopg2がらみでエラー。元のフォルダに戻しても再起不能でした。というわけでポータブルには使えず、常用するなら最初からインストール先の固定が必須のようです(少なくともWindowsでは)。
R:\moved\venv>python -m pip install pgcli
(...)
Installing collected packages: psycopg2
  Found existing installation: psycopg2 2.5.2
Exception:
Traceback (most recent call last):
(...)
IOError: [Errno 2] No such file or directory: 'r:\\moved\\venv\\lib\\site-packages\\psycopg2-2.5.2.dist-info\\RECORD' 


コマンドプロンプトで使う

気を取り直して再度、元のvenvフォルダをコピーしてインストール。起動・DB接続はpsqlと同様です。↓ 最下行に3つのファンクションキーが出て、うちF2でオートコンプリート(入力補完、Smart Completion)のON・OFF。いきなり高機能っぽい。


↓ 例えばsを打ったところ。コマンドプロンプトでもこんな風にできるとは驚き。


ただ今回は、F2OFFにしてもオートコンプリートが効きっ放し。表示内容も、構文の位置に関係なくキーワードがたくさん出たり、メタコマンドは右側に説明が付いたりと、少し親切すぎる?


ConEmuで使う

CMDシェルを開いて起動すると ↓ コマンドプロンプトと同様に使えました。文字色については、ConEmuの設定等の問題かもしれませんが、白になるべき所が黒のままだったり(画像2枚目)、時々は起動直後からエスケープシーケンスが作用せずそのまま文字として表示されることも。


psqlとの比較

オートコンプリートを見ると「おおっ!」って感じですが、psqlに比べて制約も。例えばメタコマンドの全てが移植されてる訳でなく、関数の定義文を見る\sfは未実装。シェルコマンドを呼ぶ\!も使えません。個人的にはこれが痛い。
postgres> \sf
Not Yet Implemented.


またWindowsでは避けて通れないエンコーディング問題。以前書いたように(
昨年720 / 今年112)コマンドプロンプト上のpsqlは、UTF-8にしかない文字を受け取るとエラーになります。一方pgcliはエラーで終わらず異常終了になるので ↓ 実用面でちょっと。根本原因がWindowsにあるとは言え…。
postgres> select chr(12354); -- Shift JIS にある文字はOK
+-------+
| chr   |
|-------|
| あ    |
+-------+
SELECT 1
Time: 0.015s

postgres> select chr(12436); -- Shift JIS にない文字はNG
Traceback (most recent call last):
  File "r:\venv\lib\runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "r:\venv\lib\runpy.py", line 72, in _run_code
    exec code in run_globals
  File "R:\venv\Scripts\pgcli.exe\__main__.py", line 9, in 
  File "r:\venv\lib\site-packages\click\core.py", line 716, in __call__
    return self.main(*args, **kwargs)
  File "r:\venv\lib\site-packages\click\core.py", line 696, in main
    rv = self.invoke(ctx)
  File "r:\venv\lib\site-packages\click\core.py", line 889, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "r:\venv\lib\site-packages\click\core.py", line 534, in invoke
    return callback(*args, **kwargs)
  File "r:\venv\lib\site-packages\pgcli\main.py", line 593, in cli
    pgcli.run_cli()
  File "r:\venv\lib\site-packages\pgcli\main.py", line 328, in run_cli
    click.echo_via_pager('\n'.join(output))
  File "r:\venv\lib\site-packages\click\termui.py", line 213, in echo_via_pager
    return pager(text + '\n', color)
  File "r:\venv\lib\site-packages\click\_termui_impl.py", line 287, in pager
    return _tempfilepager(text, 'more <', color)
  File "r:\venv\lib\site-packages\click\_termui_impl.py", line 357, in _tempfilepager
    f.write(text.encode(encoding))
UnicodeEncodeError: 'cp932' codec can't encode character u'\u3094' in position 32: illegal multibyte sequence 


余談ですがCygwinpsqlは、全くフツーにUTF-8を扱えます。上で問題の起きたクエリも ↓ このように。pgcliCygwin上で試すといいかもですが、当面はメタコマンドの件があるので自分は見送り。
# select chr(12436); 
+-----+
| chr |
+-----+
| ゔ  |
+-----+
(1 row)