subprocess.Popen を使用して、Scipy スタック用の自動ビルド スクリプトを作成しています。
私の現在のプロセスは以下の通りです。
mathbuild.json:
{"suitesparse": {"version": "4.2.1",
"dependencies": ["metis"],
"downloads": ["http://www.cise.ufl.edu/research/sparse/SuiteSparse/SuiteSparse-4.2.1.tar.gz"],
"build": ["cd $DL_DIR",
"tar xvfz SuiteSparse-4.2.1.tar.gz",
"cd SuiteSparse",
"cp -r $DL_DIR/metis-4.0.3 metis-4.0.3"]},
"metis": {"version": "4.0.3",
"dependencies": [],
"downloads": ["http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.3.tar.gz"],
"build": ["cd $DL_DIR",
"tar xvfz metis-4.0.3.tar.gz",
"cd metis-4.0.3",
"make"]}}
mathbuild.py:
def package_list(package, config):
for dependency in config[package]['dependencies']:
yield from package_list(dependency, config)
yield package
def build_package(package, config):
command = '; '.join(config[package]['build'])
build = subprocess.Popen(command, shell=True)
def process_package(package, config, env_dir, dl_dir):
print('INSTALLING {0}'.format(package))
print('Downloading...')
download_package(package, config, dl_dir)
print('Building...')
build_package(package, config)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Install Pylab in a new venv.')
parser.add_argument('env_dir', help='target directory for new environment')
args = parser.parse_args()
os.environ['ENV_DIR'], os.environ['DL_DIR'] = create_venv(args.env_dir)
with open('mathbuild.json') as f:
cfg = json.load(f)
processed = []
for package in package_list('suitesparse', cfg):
if package not in processed:
process_package(package, cfg,
os.environ['ENV_DIR'],
os.environ['DL_DIR'])
processed += [package]
依存関係のリストを作成し (後の項目が前の項目に依存するように)、それぞれを処理します (ダウンロードしてから、json ファイルのコマンドに基づいてビルドします)。
subprocess.Popen
問題は、依存関係が完全に構築される前に、新しい呼び出しによってパッケージが構築されていることです。上記の例では、ビルドが完了するsuitesparse
前に実行が開始されます。これは、前のサブプロセスが完了しているかどうかに関係なくmetis
、ループのたびに新しいサブプロセスを開いているためだと思います。for package in package_list('suitesparse', cfg)
質問 ループベースの Popen 呼び出しを同期して、各呼び出しが Popen への前の呼び出し (つまり、リスト内の前の項目) が完了したときにのみ開始されるようにする最良の方法は何ですか?
私が 試したこと ループを変更して、1 つの結合された Popen (両方のパッケージ ビルド) をビルドするように試みましたが、それはハックのようです。