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 件のコメント:
コメントを投稿