subprocess.check_output()を使って間接的にpsqlを実行しようとして「psql: 無効なオプション -- ' '
」というエラーに遭遇しました。このメッセージだけでは何が悪いのか判らなかったので色々試して原因を探りました。
結果、引数の作り方に問題があることが分かりました。
問題
リモートからPostgreSQLサーバのユーザをリストアップするコマンドをPythonで実行しました。
問題コードpsql01.py
#!/usr/bin/env python
import subprocess
cmd = [
'psql',
'-U ' + 'postgres',
'-d ' + 'postgres',
'-t ',
'-c ' + 'select * from pg_user;'
]
try:
result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
result = e.output
print result
コマンド実行(エラー)
[user001@localhost ~]$ python psql01.py
['psql', '-U postgres', '-d postgres', '-t ', '-c select * from pg_user;']
psql: 無効なオプション -- ' '
詳細は "psql --help" をごらんください。
解決
上記サンプルコードのcmd変数に設定するcheck_output()の第2引数の作り方を改修しました。
check_outputの文法
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
例えばbashやC言語でコマンドラインを(getopt等で)解析する際は空白文字をデリミタとして解釈しますが、check_output()はリストの要素が引数の要素になるようです。悪い言い方をすれば、check_output()は空白文字をデリミタとして扱ってくれないようです。
たぶんこれが正しい使い方
cmd = [
'psql',
'-U' , 'postgres',
'-d' , 'postgres',
'-t',
'-c' , 'select * from pg_user;'
]
これでもOK
cmd = [
'psql',
'-U' + 'postgres',
'-d' + 'postgres',
'-t',
'-c' + 'select * from pg_user;'
]
環境
- CentOS 7.4
- Python 2.7.5
補足
- subprocess.Popen()を使っていればすんなりいってたのですが。
- 「
psql: 無効なオプション -- ' '
」というエラーは、'-t△'(tの後に空白文字)の文法エラーを指していたようです。