我正在使用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的上一次调用(即列表中的前一项)完成时启动?
--我尝试过的--我尝试过更改循环,以便它构建一个合并的Popen (与这两个包构建一起),但这似乎有点麻烦。
发布于 2013-06-24 03:14:22
看起来你想要的是subprocess.check_call()而不是Popen。来自医生们
运行带有参数的命令。等待命令完成。如果返回代码为零,则返回,否则引发CalledProcessError。
您的构建函数应该类似于:
def build_package(package, config):
command = '; '.join(config[package]['build'])
subprocess.check_call(command, shell=True)如果您实际使用的是Popen对象,则可以调用wait()方法等待子命令完成:
def build_package(package, config):
command = '; '.join(config[package]['build'])
build = subprocess.Popen(command, shell=True)
# do something with the build object
build.wait()
# command is donehttps://stackoverflow.com/questions/17267411
复制相似问题