何かを書き留める何か

数学や読んだ本について書く何かです。最近は社会人として生き残りの術を学ぶ日々です。

『Effective Python』Item 36: 子プロセスを制御するためにsubprocessを使おう

『Effective Python』の続き。想像以上につらい。 www.effectivepython.com

Item 36から「Concurrency and Parallelism(並行と並列)」と題してPythonによる並行・並列プログラミングのコツを解説…となるのはよいが2つ問題がある。

  1. 私が並列・並行プログラミングをよく知らない!
  2. 私の環境(Windows Vista 32bit!!!)ではサンプルプログラムが動かない!

前者は「お前がアホなだけだろ」という話であり、後者は「そんな古い環境だから…」とか「Windowsなんて使うから…」という突っ込みが入るのでどうしようもない。

子プロセスを扱う方法として、以前はpopenpopen2os.exec*を使っていたが、subprocessを使いましょうと述べている。

Windowsだと、次のサンプルコードは簡単には動作しない

import os
import subprocess


def run_openssl(data):
    env = os.environ.copy()
    env['password'] = b'\xe24U\n\xd0Ql3S\x11'
    proc = subprocess.Popen(
        ['openssl', 'enc', '-des3', '-pass', 'env:password'],
        env=env,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE)
    proc.stdin.write(data)
    proc.stdin.flush()  # Ensure the child gets input
    return proc


procs = []
for _ in range(3):
    data = os.urandom(10)
    proc = run_openssl(data)
    procs.append(proc)

for proc in procs:
    out, err = proc.communicate()
    print(out[-10:])

まずOpenSSLが必要という暗黙の条件もあるが、それを解決したとしても

TypeError: environment can only contain strings

という例外が返される。 果たしてこの例外がどこからやってきたのか、すぐにわかるだろうか…。