shell 多进程调用python脚本并控制参数(并行调参)

今天接到领导的一个需求,说:test.py是模型运行文件,每调用十次取一次平均值作为结果。现要对其并行调参,由于是在linux下,当然选择shell啦,很简易的需求,由于菜搞了半天才搞运行,代码设计美感毫无。shell小白可以参考,大神还请帮我解答个问题:如何将调用py文件的输出保存为变量?真心求解,望不吝赐教

先贴一下工程目录:

shell 多进程调用python脚本并控制参数(并行调参)_第1张图片

环境是在AI studio下,上面那个release_datasets不要管他,总共三个文件:test.py,loop.sh,sumToAve.py

直接贴代码:

loop.sh

#! /bin/bash 
# $1是调用shell输入的第一个参数
#echo 'redirect to file:' $1
maxParallel=5
maxLoop=10
AveFileRedirect='ave.txt'
: > $AveFileRedirect

fileRedirect[0]='result100.txt'
fileRedirect[1]='result101.txt'
fileRedirect[2]='result102.txt'
fileRedirect[3]='result103.txt'
fileRedirect[4]='result104.txt'

paras[0]='--train_percentage=0.6 --connected_nodes_file_path=data/cora0 --file_redirect='${fileRedirect[0]}
paras[1]='--train_percentage=0.7 --connected_nodes_file_path=data/cora1 --file_redirect='${fileRedirect[1]}
paras[2]='--train_percentage=0.8 --connected_nodes_file_path=data/cora2 --file_redirect='${fileRedirect[2]}
paras[3]='--train_percentage=0.9 --connected_nodes_file_path=data/cora3 --file_redirect='${fileRedirect[3]}
paras[4]='--train_percentage=1.0 --connected_nodes_file_path=data/cora4 --file_redirect='${fileRedirect[4]}

for ((p=0; p<$maxParallel; p++))
do
    {
    : > ${fileRedirect[p]}
    for ((l=0; l<$maxLoop; l++)) 
    do
        echo '外循环第 '$p' 次, ''内循环第' $l '次'
        python test.py ${paras[p]}
        sleep 0.5
    done
    echo '外循环第' $p' 次结束' 
    paraForAve='--ave_file_redirect='$AveFileRedirect' --file_redirect='${fileRedirect[p]}
    python sumToAve.py $paraForAve
    }&
done
wait

1.其实全靠外层for的这个大括号和&起作用,可以参考引文第一个博客,加上这个&就能实现多进程,去掉就串行执行

2.: > $AveFileRedirect这个操作是利用重定向将后面这个变量代表的文件清空

3.要注意在调用python文件的时候,传参数列表最好写成一个变量,再给他传变量,不然我这边出了无法解析参数的bug

4.注意数组使用,访问时要加一个大括号 ${paras[p]} 这样

sumToAve.py:

import argparse
import re
parser = argparse.ArgumentParser()
parser.add_argument("--file_redirect", type=str, default="")
parser.add_argument("--ave_file_redirect", type=str, default="")
args = parser.parse_args()

with open(args.file_redirect, 'r') as f:
    l = f.readlines()
regex = re.compile('test accuracy: (.*?) end')  
puredL = regex.findall(str(l))
#print(puredL)
assert (len(puredL) == 10), args.file_redirect+'文件中不是十个数'
sum = 0
for i in range(len(puredL)):
    sum += float(puredL[i])
sum /= 10
#print(sum)
with open(args.ave_file_redirect, 'a') as f:
    f.write('Result of '+args.file_redirect+' is '+str(sum)+'\n')

这个文件没什么好说的,它的出现纯属是因为我不知道如何在sh中直接利用test.py的输出,查了需要改test.py,看起来很奇怪,不希望对源代码做那样的改动,如果有大神知道简便的方式希望能不吝赐教。

test.py

import argparse
strToWrite = 'test accuracy: 0.1234567890123456 end'

parser = argparse.ArgumentParser()
parser.add_argument("--train_percentage", type=float, default="-1")
parser.add_argument("--connected_nodes_file_path", type=str, default='err')
parser.add_argument("--file_redirect", type=str, default='err')
args = parser.parse_args()
print(args.train_percentage)
print(args.connected_nodes_file_path)
print(args.file_redirect)
with open(args.file_redirect, 'a') as file:
    file.write(strToWrite + '\n')

贴一下运行效果:

shell 多进程调用python脚本并控制参数(并行调参)_第2张图片

可以看到外循环是交替出现的,实现了并发。

还有一处bug,每次运行完后会打出程序中的所有echo以及一些代码,关于这个怎么回事我是一点没得头绪,希望有领导知道的话告诉我一下哈。这总结博客写的赶上提问博客了。

shell 多进程调用python脚本并控制参数(并行调参)_第3张图片

参考博客:

Shell-使用&和wait让你的脚本并行执行

python函数调用时参数传递方式

Shell中数组的使用

Linux Shell实现多进程并发执行

shell脚本中执行python脚本并接收其返回值的例子

你可能感兴趣的:(shell)