在运筹学算法研究中,每种算法的设计完成后都需要大量的数值试验来验证该算法的效果,并与benchmark/baseline相比较。其中,每组数值试验中需要在算法中修改一定的参数,然后在算法完成后输出算法效果。在以往时刻,由于个人能力的欠缺,我往往是采用手动输入和输出的方式,即每次手动修改算法中的参数,点击运行,利用excel表格等工具记录输出结果,每个实例都需要重复一次。毫无疑问,这种方法是极其傻瓜的,因此打算此后都通过python脚本来自动化运行数值试验,通过csv文件将参数传入程序,然后将输出结果写入”.txt”文件中,每次执行多组数值试验,实现真正意义上的一劳永逸。
Python 系统调用——运行其他程序
脚本自动化的基础是python的特性。在python中,可以方便地调用os模块运行其他的脚本或程序,这给了我们在在脚本中直接使用其他脚本的可能。而这种调用方式往往分为以下几种:
1. os.system()
os模块中的system()函数可以方便地运行其他程序或者脚本。其函数原型如下:
os.system(command)
command是要执行地命令,相当于在cmd窗口中输入的命令。如果要向程序或脚本传递参数,可以使用空格分隔程序及多个参数。
import os
os.system('notepad') # 打开记事本程序
os.system('notepad 1.txt') # 打开1.txt文件,若不存在则创建
2. ShellExecute
win32api模块中的ShellExecute函数同样可以实现该功能。其函数原型如下:
ShellExecute(hwnd, op, file, params, dir, bShow)
其函数含义如下所示:
- hwnd:父窗口的句柄,如果没有父窗口,则为0
- op:要进行的操作,为”open“、”print“或者为空
- file:要运行的程序,或者打开的脚本
- params:要向程序传递的参数,如果打开的为文件,则为空
- dir:程序初始化的目录
- bShow:是否显示窗口
import win32api
#在后台运行记事本程序
win32api.ShellExecute(0, 'open', 'notepad.exe', '', '', 0)
#向记事本传递参数,打开python.txt
win32api.ShellExecute(0, 'open', 'notepad.exe', 'python.txt','',1)
3. CreateProcess
4. ctypes
python脚本实例
import pandas as pd
import os
import win32api
# 打开需要执行的算法程序.exe文件所在目录
os.chdir(r'D:\zhangyue\Algorithm\2022-11-01 CSSLSP_ADP\Debug')
# 后台执行程序
for i in range(1, 10):
win32api.ShellExecute(0, 'open', '2022-11-01 CSSLSP_ADP.exe',
f'input_params.csv
C:\\zhangyue\\log_{i}.txt
{7}
{0.1}
C:\\zhangyue\\train_{i}.csv
C:\\zhangyue\\train_lam{i}.csv',
'',
0
)
cpp程序
#include "Tabu_search.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[]){
file_in_path = argv[1]; //文件读取路径:input_params.csv
file_out_path = argv[2]; //文件输出路径:C:\\zhangyue\\log_{i}.txt
fole_train_save = argv[5]; //文件训练路径:C:\\zhangyue\\train_{i}.csv
fole_train_lam= argv[6]; //文件训练路径:C:\\zhangyue\\train_lam{i}.csv
LENGTH_TABU = atof(argv[3]); //禁忌表长度参数读取
PENALTY_COEF = atof(argv[4]); //惩罚系数参数读取
//将原本输出在控制台的字符重定向,输出到指定的路径文件中
freopen(file_out_path.c_str(), "w", stdout);
for (int i = 0; i < argc; i++)
cout << argv[i] << "\t";
cout << endl;
ifstream ifile(fole_train_lam, ios::in);
string line;
getline(ifile, line); //在ifile中接收line的值
istringstream sin(line); //定义一个字符串输入流对象sin,将line中所包含的字符串 放入其中
string tmp;
for (int t = 0; t < T; ++t) //获取一个数据
{
getline(sin, tmp, ',');
lambda[t]=(stod(tmp)); //存到temp中
}
TabuSearch alg(file_in_path);
//alg.read_init_sol();
alg.run();
return 0;
}