Python3.2: subprocess モジュールでコマンドラインを bytes で書くと TypeError が発生
事象
POSIX互換環境の Python 3.2 で subprocess#call を呼び出すとき
コマンドを bytes で書きつつ shell モードを有効にすると、以下の意味不明なエラーが出る。
$ python Python 3.2.5 (default, Sep 1 2015, 23:07:07) [GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> subprocess.call(b'echo', shell=True) (snip) TypeError: Can't convert 'int' object to str implicitly >>>
コマンドを str で渡せばよいのだが、それだとコマンドライン自体が SJIS などの非UTF-8で表現されている場合に困ってしまう。
原因
子プロセスを生成するところで、args に ['/bin/sh', '-c', 101, 99, 104, 111] というパラメータが渡っていた。
['/bin/sh', '-c'] + list(b'echo') のようなコードで作られたようだ。
1バイトごとに分解され int となったものが暗黙的に str に変換されずに TypeError が送出される。
Python 3.3 では修正済み。
- Issue #8513: On UNIX, subprocess supports bytes command string. · python/cpython@ae1258d
- Issue 8513: subprocess: support bytes program name (POSIX) - Python tracker
対応方法
Python 3.2 をサポートしないのが賢明と思われるが、以下のようなワークアラウンドでも回避できそうだ。
import subprocess NOT_USE_SHELL = sys.version_info[:2] == (3, 2) and not sys.platform == 'win32' cmd = b'echo' if NOT_USE_SHELL: ret_code = subprocess.call(['/bin/sh', '-c', cmd], shell=False) else: ret_code = subprocess.call(cmd, shell=True)
話題になったのが 5年以上前ということもあり、Google検索しても情報が出てこないのがつらい。
0 件のコメント:
コメントを投稿